#clj-kondo

generated UTC: 2023-11-22 19:47
latest data: https://clojurians-log.clojureverse.org/clj-kondo/2023-11-14
messages: 24626
pro tips:
* Double click on text to filter by it. (doubleclick + cmd-f for extra points).
* Click on date to keep day visible regardless of filter.
* Click on time to keep hour visible regardless of filter.
#2019-04-1210:54borkdudeIf you’re feeling audacious, you can grab a binary from master via the CircleCI builds: https://circleci.com/gh/borkdude/clj-kondo/tree/master Select buildmac or buildlinux and go to Artifacts.#2019-04-1210:56borkdudeThe latest additions are cond + case linting and built-in caches for clojure.core, cljs.core + clojure.test#2019-04-1318:06mynomoto@borkdude trying clj-kondo on vim using Ale and it just worked 🎆#2019-04-1318:06borkdude😄#2019-04-1318:08borkdudefeel free to make a PR with some documentation about this, if you want#2019-04-1509:32borkdudeNew release: https://github.com/borkdude/clj-kondo/releases/tag/v2019.04.15-alpha#2019-04-1615:27borkdudehttps://twitter.com/borkdude/status/1118173943435800577#2019-04-1620:06borkdudeFeedback welcome: https://github.com/borkdude/clj-kondo/issues/9#2019-04-2121:16borkdudeclj-kondo 2019.04.21-alpha: https://github.com/borkdude/clj-kondo/releases/tag/v2019.04.21-alpha also, https://github.com/borkdude/flycheck-clj-kondo is now available on MELPA#2019-04-2512:54borkdudehttps://github.com/borkdude/clj-kondo/releases/tag/v2019.04.25-alpha#2019-05-0119:42borkdudehttps://github.com/borkdude/clj-kondo/releases/tag/v2019.05.01-alpha#2019-05-0616:11fmnoisehi#2019-05-0616:11fmnoiseis there any way to check external function calls via flycheck?#2019-05-0616:13borkdudeyeah. you need to setup a .clj-kondo directory in the root of your project and then populate it by linting your classpath with the --cache option#2019-05-0616:13borkdude@fmnoise https://github.com/borkdude/clj-kondo/#project-setup#2019-05-0616:22fmnoisethanks @borkdude, trying that#2019-05-0616:26fmnoisethanks, that works#2019-05-0616:36borkdude😄#2019-05-0617:35fmnoisedo you have an example of how to exclude some external libs from linting?#2019-05-0617:35fmnoiseI got some errors on manifold, aleph and some other stuff#2019-05-0716:23Marc O'MorainInteresting error using clj-kondo v2019.05.06-alpha: /Users/marc/dev/circleci/circle/src/circle/web/http/routes/outer.clj:0:0: error: can't parse /Users/marc/dev/circleci/circle/src/circle/web/http/routes/outer.clj, No implementation of method: :sexpr of protocol: #'rewrite-clj.node.protocols/Node found for class: nil#2019-05-0716:24Marc O'MorainThese files have clojure dating from 2012-11-07 😄#2019-05-0716:28Marc O'MorainFound it:
$ echo '(fn)' | clj-kondo --lint -
<stdin>:0:0: error: can't parse <stdin>, No implementation of method: :sexpr of protocol: #'rewrite-clj.node.protocols/Node found for class: nil
linting took 3ms, errors: 1, warnings: 0
#2019-05-0719:58Marc O'MorainAnd here is a similar one:
$ echo '(doseq [send [inc]] (send 1))' | clj-kondo --lint -
<stdin>:1:21: error: wrong number of args (1) passed to clojure.core/send
#2019-05-0808:46borkdude@marc-omorain (fn) isn’t valid in clojure, right?#2019-05-0808:46borkdudedoseq is giving a false positive here, I’ll fix that#2019-05-0808:47borkdudeoh I see, (let [fn (fn [])] (fn)) isn’t working. I’ll fix that too 🙂#2019-05-0809:05Marc O'MorainYes, this is the case - a higher order function takes a formal arg named fn#2019-05-0809:05borkdudethanks, I’ve made a GH issue for it and I’ll fix it before the next release#2019-05-0916:50pez@borkdude, where here on Slack did Martin mention he was looking for maintainers of the linter extension?#2019-05-0916:50borkdudeprivate conversation#2019-05-0916:51borkdudehe didn’t say he was looking, but he was willing to pass it on#2019-05-0916:51pezSemantics. 😃#2019-05-0916:51borkdude🙂#2019-05-0916:55pezMaybe it is something for you @marc-omorain? I happen to know you know your way around VS Code API:s. 😏#2019-05-0916:56Marc O'MorainI would indeed like that#2019-05-0917:10pezI'm super happy to hear! I'll be going offline for a while now, but please start the convo in a PM. #2019-05-1219:39borkdudeclj-kondo v2019.05.12-alpha is out now! https://github.com/borkdude/clj-kondo/releases/tag/v2019.05.12-alpha#2019-05-1411:33Marc O'MorainTrying on our app now. One suggestion /Users/marc/dev/circleci/circle/test/circle/bitbucket/test_client.clj:4:14: warning: unused namespace cheshire.core On first reading, this made my think that a namespace was unused - in fact it’s the import that’s not used. Maybe this would be more clear: > warning: required namespace is unused#2019-05-1411:43pezTSLint would phrase it something like namespace cheshire.core is required, but never used.#2019-05-1412:01borkdudeok, can you put this into an issue? I’d be happy to rephrase#2019-05-1412:02borkdudealso, I’m wondering about the message about (cond 1 2), I’m still pondering about a better message there#2019-05-1412:02borkdudefeel free to post it in the same issue#2019-05-1415:14borkdudeI would be happy to change the message, but note that this is exactly the same output as joker: https://www.dropbox.com/s/xqep75nq3v6wu1r/Screenshot%202019-05-14%2017.14.28.png?dl=0#2019-05-1417:34borkdudehttps://twitter.com/borkdude/status/1128352837510074374#2019-05-1421:58borkdudeyou can try an early Windows version: https://twitter.com/borkdude/status/1128419191588106241#2019-05-1517:27mynomotoIs the plan for clj-kondo to do everything that the joker linter does?#2019-05-1517:52borkdudestep by step, maybe#2019-05-1517:56borkdudewhat are the most pressing things you are missing from joker?#2019-05-1716:57mynomotoUnused bindings and using undefined vars. And then I wouldn't need joker anymore. 😃#2019-05-1717:35borkdudehttps://github.com/borkdude/clj-kondo/issues/173 https://github.com/borkdude/clj-kondo/issues/174 with unresolved vars I’m a little bit concerned about too many false positive, e.g. when people use (use 'foo), etc.#2019-05-1717:40mynomotoI would be happy with what joker does, do not support use nor :refer-all. You need to help yourself too 😉#2019-05-1717:40borkdudeyeah. a little secret is that clj-kondo totally ignores use right now#2019-05-1717:40borkdudeI think that’s the direction the community should be taking. clojurescript also doesn’t support it 😉#2019-05-1717:44mynomotoIt would be nice to use regex for exclusions of unused namespaces. Something like .*\.spec#2019-05-1717:46borkdudeI guess that’s possible without affecting current users of the config. which is {:linters {:unused-namespace {:exclude [some.namespace/foo]}#2019-05-1717:46borkdudewe could just allow strings in there and interpret them as regex maybe#2019-05-1717:47mynomotoThat should work. 👍:skin-tone-2:#2019-05-1717:49borkdudehttps://github.com/borkdude/clj-kondo/issues/175#2019-05-1721:23mynomotoGreat! 🎆#2019-05-1609:06borkdude@marc-omorain https://www.dropbox.com/s/r96ntgce3kps3w3/Screenshot%202019-05-16%2011.06.27.png?dl=0#2019-05-1609:07Marc O'Morainsweet#2019-05-1609:07Marc O'Morainbtw, when I upgraded to the latest release, the number warnings in our main codebase went from 73 to 340 😄#2019-05-1609:07Marc O'MorainI believe they are all legit#2019-05-1609:08borkdudewhoops 🙂 if there any false positives, please notify me#2019-05-1609:08borkdudethere were some false positives regarding unused namespaces which @mynomoto reported, these are now fixed on master#2019-05-1609:08Marc O'Morain
> clj-kondo --lint . | tail -1
linting took 12508ms, errors: 11, warnings: 122
> clj-kondo --lint "$(lein classpath)" | tail -1
linting took 45004ms, errors: 268, warnings: 487
> lein clj-kondo --lint . | tail -1
linting took 9267ms, errors: 0, warnings: 0
> lein clj-kondo --lint "$(lein classpath)" | tail -1
linting took 23855ms, errors: 0, warnings: 306
One of my colleagues has noticed some non-determinism yesterday.
#2019-05-1609:09Marc O'MorainI’ve not looked in this yet.#2019-05-1609:09borkdudeyeah, the lein version can be faster because of JIT I guess#2019-05-1609:10borkdudeso for big workloads the JVM might be the preferred mode#2019-05-1609:11Marc O'MorainThe issue is that the number of warnings changed#2019-05-1609:11borkdudeI’m still not entirely happy about this message: https://www.dropbox.com/s/7pmy4t8x7hzzgl7/Screenshot%202019-05-16%2011.08.52.png?dl=0#2019-05-1609:12borkdude@marc-omorain that shouldn’t be the case, so it’s either a bug or you’re not using the same version. can you check by doing clj-kondo --version vs lein clj-kondo --version?#2019-05-1609:12Marc O'Morainoh that’s it! I didn’t see that one invocation was from lein and one wasnt#2019-05-1609:49Marc O'MorainWe’ve found one fun false positive. We have a test that calls (is (thrown+ ...)), and that namespace requires slingshot.test, which is marked as unused. is calls a multimethod assert-expr which is defined for the thrown? and thrown-with-msg? symbols by clojure.test. slingshot.test adds methods for thrown+? and thrown+-with-msg?. By requiring slingshot.test we are extending the multimethod.#2019-05-1610:01borkdude@marc-omorain
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "e3a18c918887968786a38e8a808b8a868f"}, :content ("[email protected]")}
#2019-05-1610:01borkdudeMaybe I should change the name :unused-namespace to something else?#2019-05-1610:01Marc O'MorainMY colleague has just committed that 😄#2019-05-1610:02Marc O'Morain
(deftest two-cases
  (let [resource (load-some-resource)]
    (let [result (do-something resource)]
      (is (= 2 (count result))))
    (let [result (do-something-else resource)]
      (is (= 3 (count result))))))
We have some tests like this that complains about a redundant let ^
#2019-05-1610:06borkdudeusually a redundant let is really redundant, but in this case probably not. you could write:
(deftest two-cases
  (let [resource (load-some-resource)
        result (do-something resource)
        _ (is (= 2 (count result)))
        result (do-something-else resource)]
    (is (= 3 (count result)))))
not sure how clj-kondo should be configured to be silent about this case. I’ll think about it. maybe the redundant let can be more intelligent
#2019-05-1610:07borkdudemaybe redundant let should only complain if there is one single child in a let that is a let, that seems reasonable#2019-05-1610:10borkdude@marc-omorain https://github.com/borkdude/clj-kondo/issues/170#2019-05-1610:49Marc O'Morain👍#2019-05-1610:49Marc O'MorainWe are about to remove a load of test harness with clj-kondo#2019-05-1610:50Marc O'MorainWe have a script that asserts that every namespace in src is required from a file in test.#2019-05-1610:52Marc O'MorainThis was put in place when someone committed a file in src that didn’t compile, it never had a test, and it broken in prod#2019-05-1610:52Marc O'MorainWe can now just lein clj-kondo --lint ${lein classpath}#2019-05-1611:10borkdudecool!#2019-05-1718:56borkdudeWindows installation has gotten easier: https://twitter.com/borkdude/status/1129460559924080640#2019-05-1815:03borkdude@mynomoto https://github.com/borkdude/clj-kondo/issues/175#2019-05-1820:02borkdude@marc-omorain the redudant let change is in: https://github.com/borkdude/clj-kondo/issues/170 I think I’ll make a release tomorrow, I tested it quite extensively, so I think it’s good. If there’s anything to be changed, we can also do it after the release if you didn’t get a chance to test#2019-05-1915:28borkdudeclj-kondo (clojure linter) v2019.05.19-alpha is out! - Release info: https://github.com/borkdude/clj-kondo/releases/tag/v2019.05.19-alpha - Install via scoop on Windows: https://github.com/borkdude/clj-kondo/blob/master/doc/install.md#scoop-windows - Install via brew on Linux and MacOS: https://github.com/borkdude/clj-kondo/blob/master/doc/install.md#brew-macos-and-linux#2019-05-2009:10borkdudein this thread Simon wants to make a linter plugin for LightTable https://twitter.com/simon_brooke/status/1130399052296859648#2019-05-2009:10borkdudekind of same idea for VSCode (cc @marc-omorain @pez)#2019-05-2009:12pezWhat's the ”kondo” reference? 😃#2019-05-2009:12borkdudehttps://konmari.com/pages/about#2019-05-2020:01borkdudeany preference? (the difference is in the word keyword): https://www.dropbox.com/s/qw3mjjtv48fohzv/Screenshot%202019-05-20%2022.01.30.png?dl=0#2019-05-2023:28mynomotoI like the one with keyword better.#2019-05-2107:29borkdudeok, then I’ll keep that one#2019-05-2114:23mynomotoCache is not working on my machine with the latest clj-kondo v2019.05.19-alpha. Any suggestion on how to debug it? I have a .clj-kondo dir on project root and I'm running clj-kondo on project root with clj-kondo --lint "$(clj -A:dev -Spath)" --cache#2019-05-2114:24mynomotoIgnore me, cache is on a hidden directory 🙈#2019-05-2114:30borkdudeyeah, it should be in .clj-kondo/.cache/v2019.05.19-alpha/...#2019-05-2114:30borkdudeVim docs are added by @rahul080327: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#vimneovim#2019-05-2307:45borkdudeclj-kondo can now also be used with Docker: https://github.com/borkdude/clj-kondo/blob/master/doc/install.md#docker#2019-05-2408:54borkdudeI’m going over some rewording of messages here: https://github.com/borkdude/clj-kondo/issues/197#2019-05-2408:55borkdudeif you want, you can suggest improvements there#2019-05-2520:06borkdudeI’ll probably release a new version tomorrow. If you want to try a non-Docker pre-release, let me know. The Docker image with the tag 2019.05.20-alpha-SNAPSHOT is the most recent version. Here’s how you can run it with Docker: https://github.com/borkdude/clj-kondo/blob/master/doc/install.md#docker#2019-05-2520:07borkdudeThese are the issues that have been solved and will be released: https://github.com/borkdude/clj-kondo/issues?q=is%3Aissue+is%3Aopen+label%3Anext-release#2019-05-2618:52borkdudeclj-kondo v2019.05.26-alpha! 🎉 https://github.com/borkdude/clj-kondo/releases/tag/v2019.05.26-alpha#2019-05-2815:21borkdudeAny other volunteers wanting to test a new feature called “unused bindings”? https://github.com/borkdude/clj-kondo/issues/173#issuecomment-496563463#2019-05-2823:41kennyThe install for IntelliJ IDEA located: https://cljdoc.org/d/clj-kondo/clj-kondo/2019.05.27-SNAPSHOT-alpha/doc/editor-integration#intellij-idea always will open the console because the command exits with a non-zero status. You need to set Show console to Never.#2019-05-2823:44kennyI am testing clj-kondo out on one of my projects. There's one false positive that I'm seeing. In the ns, I have
(ns foo
  (:require
    [honeysql-postgres.format]))
clj-kondo says: "warning: namespace honeysql-postgres.format is required but never used". While this warning is correct, it actually is implicitly used. That namespace registers some defmethods to extend honeysql.
#2019-05-2823:46kennyThe same problem when require'ing namespaces that only contain specs -- the actual namespace is not aliased and does not appear to be used but it actually mutates some global state.#2019-05-2903:12borkdude@kenny you can visit the docs, configuration and there you will see how to exclude namespaces from being warned about. You can also use a regex #2019-05-2903:13borkdudeI’ll make a new screenshot, thanks#2019-05-2912:04borkdude@kenny the screenshot is updated#2019-05-2912:07borkdude@kenny Here are the config docs I referred to (I was on mobile earlier): https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-required-but-unused-namespace-from-being-reported#2019-05-2916:22kenny@borkdude Thanks! Curious, is there a way to send info from the editor to clj-kondo? It'd be cool if I could alt+enter over a unused namespace and mark it as excluded.#2019-05-2916:29borkdudenot yet. what editor are you using?#2019-05-2916:30kennyCursive#2019-05-2916:30borkdudeI’ve also been thinking of something like this:
(ns example
  {:clj-kondo/config
   {:linters {:unused-namespace {:exclude ['clojure.string]}}}}
  (:require [clojure.string]))
so you can have a namespace local config, if you don’t want to have the namespace excluded everywhere
#2019-05-2916:31borkdudebut to answer your question: I guess you would have to write editor-specific code to add something to the clj-kondo configuration file, that isn’t something clj-kondo provides for all editors#2019-05-2916:33borkdudenote that you can also use a regex in the config, if you have many similar names#2019-05-2916:35kennyHmm. Not sure if I'd want to add that to my namespace but that could be useful. I see. It;s unfortunate that there isn't a common interface for describing these lint-esque problems.#2019-05-2916:37kennyBTW I could see it being useful to exclude a ns like foo.specs but also still want a lint check for something like this [foo.specs :as foo-specs], noting that foo-specs is not used anywhere.#2019-05-2916:41borkdudefeel free to post an issue about it#2019-05-2921:36borkdudetesting the new “unused bindings” feature is still appreciated. https://github.com/borkdude/clj-kondo/issues/173#2019-05-3009:51borkdudeI consider the “unused bindings” feature done now. Feel free to test and report back: https://github.com/borkdude/clj-kondo/issues/173#2019-05-3016:32borkdudeNow moved to master …#2019-05-3118:26borkdude@stefan.van.den.oord Hi Stefan, for the shadow-cljs :default issue, what operation system are you on again, Mac I think?#2019-05-3118:27StefanYes indeed#2019-05-3118:27borkdudeOK, can you test with this one? https://3231-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.05.27-alpha-SNAPSHOT-macos-amd64.zip#2019-05-3118:27Stefansure just a sec…#2019-05-3118:29Stefan🎉 Warning gone 🙂#2019-05-3118:31borkdudeThat will hopefully be the last change before tomorrow’s release. If anyone want to test with the linux version: https://3232-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.05.27-alpha-SNAPSHOT-linux-amd64.zip#2019-06-0109:58borkdudeclj-kondo v2019.06.01-alpha! 🎉 major new feature: detecting unused function arguments and local bindings https://github.com/borkdude/clj-kondo/releases/tag/v2019.06.01-alpha#2019-06-0116:24lreadI am finally trying out clj-kondo! Very cool, and much thanks @borkdude!#2019-06-0116:27lreadI use spacemacs, do you want to add any extra guidance https://github.com/borkdude/flycheck-clj-kondo/blob/master/README.md or are folks generally expected to know what to do?#2019-06-0116:31lreadI opted to enable both joker and clj-kondo so I first added these packages to my .spacemacs config like so:
dotspacemacs-additional-packages '(flycheck-clj-kondo flycheck-joker)
And then again in .spacemacs added the following under dotspacemacs/user-config
;; setup clojure linters
  (use-package clojure-mode
    :ensure t
    :config
    (require 'flycheck-joker)
    (require 'flycheck-clj-kondo)
    (dolist (checkers '((clj-kondo-clj . clojure-joker)
                        (clj-kondo-cljs . clojurescript-joker)
                        (clj-kondo-cljc . clojure-joker)))
      (flycheck-add-next-checker (car checkers) (cons 'error (cdr checkers)))))
#2019-06-0116:34lreadI guess ideally these linters would be optionally provided by the spacemacs clojure layer: https://github.com/syl20bnr/spacemacs/tree/develop/layers/%2Blang/clojure#2019-06-0117:38borkdude@lee cool 🙂#2019-06-0118:37borkdudemade a clj-kondo demo site here: https://clj-kondo.michielborkent.nl#2019-06-0121:28lread@borkdude, that’s pretty cool!#2019-06-0202:06tianshuhow about lint on macros according to its spec#2019-06-0207:14borkdude@doglooksgood I’ve thought about doing things with spec in clj-kondo and also played with it#2019-06-0207:15borkdudebut ultimately clj-kondo has to parse code anyway and produce human readable error messages, which spec doesn’t so. also it might affect performance in a bad way, I’d like to keep clj-kondo fast#2019-06-0207:15borkdudeit also bloated the binary from 16 to 35MB, which is in this day and age, maybe not a problem#2019-06-0314:19borkduderandom clj-kondo tip: to exclude all cljsjs.* namespaces from being warned about as unused, use this config:
{:linters
  {:unused-namespace
    {:exclude ["cljsjs\\..*"]}}}
#2019-06-0316:13borkdudeKinda like this idea for expressing: this namespace is only required for side-effects (loading specs, loading a foreign lib, etc). (ns foo (:require (my-side-effecting.ns) [normal.ns])) clj-kondo could take that into account - feedback?#2019-06-0316:23kszabosomewhat related discussion: https://github.com/clojure-emacs/refactor-nrepl/pull/189#2019-06-0316:23kszaboand: https://github.com/clojure-emacs/clj-refactor.el/issues/382#2019-06-0316:24kszaboactually I really like the manual (require 'side-effecting.ns) idea below the (ns) form#2019-06-0316:31borkdude@thenonameguy yeah, but that doesn’t fly in CLJS#2019-06-0316:31borkdude(as far as I know)#2019-06-0316:44kszabotrue, I haven’t considered that#2019-06-0317:55borkdudemaybe even better (@mynomoto suggested this): don’t wrap the name at all, so: (ns foo (:require my-side-effecting.ns [normal.ns]))#2019-06-0519:47borkdudeI usually use ag for this problem, but maybe this is also useful? https://github.com/borkdude/clj-kondo/issues/234#2019-06-0709:05borkdudeclj-kondo v2019.06.07-alpha! 🎉 major new features: Clojure API, JSON/EDN output https://github.com/borkdude/clj-kondo/releases/tag/v2019.06.07-alpha#2019-06-0712:48StefanOoohhhh somebody just pointed out clojure-toolbox on #clojure. Didn’t know about that one yet, really awesome! @borkdude Are you adding clj-kondo there or do you want me to do it? 😉#2019-06-0712:51borkdude@stefan.van.den.oord I’ll give you the honors, thanks 🙂#2019-06-0713:07Stefanhttps://github.com/weavejester/clojure-toolbox.com/pull/314#2019-06-0713:08borkdudethanks#2019-06-0713:31dominicmI was just thinking about seeing this in a few places on a re-frame application, thought it might be worth detecting that it's unused & unnecessary: echo '(fn [[_ _]] 10)' | clj-kondo --lint -#2019-06-0713:33borkdude@dominicm by convention, clj-kondo ignores symbols that start with _ for detecting unused args, so that would be a new type of linter: “unnecessary destructuring”?#2019-06-0713:53dominicmThe argument which is performing destructuring is completely ignored, which is why I figured it would be unused args too, but sure :)#2019-06-0713:54borkdudeif you would do [_ _ :as x] clj-kondo would already report it 😉#2019-06-0713:54borkdudeI guess you can’t assume it’s completely unused, since destructuring fails on certain things and this may be used as a feature 🙂#2019-06-0713:55borkdudealso sometimes it serves as documentation like: a seqable of at least two elements are expected here#2019-06-0713:55dominicmYou mean that someone might be doing:
(try
  (let [[_ _] :foo] true)
  (catch Exception e
    false))
?
#2019-06-0713:56borkdudeyeah, or forcing at least two elements to be realized from a seq#2019-06-0713:57dominicmcould be docs, yeah. I'm a little ambivalent on that, it's either: 1) A repeating pattern (like re-frame) and therefore the docs are elsewhere 2) unique to this fn, in which case you're ignoring the argument for no reason.#2019-06-0713:57dominicmThat would be some funky code.#2019-06-0714:06mynomotoI just linted a re-frame app and I would love what @dominicm is suggesting.#2019-06-0714:07mynomotoNo warnings from clj-kondo on the two largest projects at work. A bunch of unused code deleted, thanks for that.#2019-06-0714:13borkdudecool, good to hear 🙂#2019-06-0714:16borkdudeI’ll think more about the [_ _] case, thanks for bringing it up#2019-06-0714:20borkdudewhat if _ is in fact used somewhere, should it then also report _ that was marked as unused, but it is used? it’s like telling the linter: ignore this, but tell me when it’s not good to ignore, which doesn’t feel right to me yet…#2019-06-0714:20dominicmMy "purist" reaction is that it shouldn't be reported as unused, because it is! But I think use of _ arguments is usually a mistake.#2019-06-0714:22borkdudethe linter already doesn’t report it as unused as of now, but if you do use it, should it report the contrary (I don’t think so). but then [_ _] would also not be reported because of this.#2019-06-0714:23borkdude_ is telling the linter: I know I’m not using this, but please don’t report anything about it#2019-06-0714:31borkdudea convention which isn’t very clear yet among the community: how do you tell tooling to keep namespaces, although they’re not used anywhere explicitly in the code.#2019-06-0714:32borkdudesome people have brought up attaching ^:keep on a vector in which the ns name is wrapped: ^:keep [do-not.remove]#2019-06-0714:33borkdudehaving it as an unwrapped to signal this could also work: (:require do-not.remove) but there might be others that are accidentally also unwrapped. also that wouldn’t work for java imports#2019-06-0714:47borkdudehttps://github.com/borkdude/clj-kondo/issues/241#2019-06-0716:17dominicmI've thought that the declaration of having side effects (e.g. registering multimethods, launching rockets) should be at the (ns) level, not the the require level#2019-06-0716:22borkdudeexample?#2019-06-0716:24borkdudemaybe an ns can be required only for side effects in some namespaces, but for referring functions in another, so I’m not sure about that#2019-06-0716:28dominicmif you require a namespace, you might be causing it's side effects. You don't know.#2019-06-0716:29borkdudenamespaces are only loaded once, normally#2019-06-0716:29borkdudeso the side effects should only happen once. when, you shouldn’t care about#2019-06-0716:30borkdudewe’re talking side effects of loading specs, multimethods. side effects like launching missiles is probably not a good idea as a top-level form 😉#2019-06-0716:32borkdudethis issue is not about documenting whether a namespace has side effects, but if you’re only loading it because of those#2019-06-0716:34borkdudesometimes tools are automatically removed “unused” requires, and you want a way to prevent that#2019-06-0716:43dominicmI understand.#2019-06-0716:51tianshu@borkdude emmm, I mean parsing the spec definition, but not using the spec. only handle the basic predicate like string?, int?, symbol? and the regexp ops like s/*, s/+, etc. by parsing the spec, it is possible to find the arity error and type error on literals.#2019-06-0716:52tianshubut the situation is complex, maybe it's not a good idea#2019-06-0717:39borkdude@doglooksgood yeah, I’ve already considered that in one of the issues: https://github.com/borkdude/clj-kondo/issues/23#2019-06-0804:52zane@borkdude Thank you for clj-kondo! ❤️#2019-06-1002:08lreadAnd @borkdude thanks also for being on the defn podcast: https://soundcloud.com/defn-771544745/50-michiel-borkent-aka-borkdude It was a delightful and educational listen!#2019-06-1006:31sogaiu@borkdude i am getting what look like some duplicate results when running clj-kondo (3797573ebe1dfb1689f819dcaa0777cd1060caa4) on https://github.com/weavejester/cljfmt/blob/3c6fbde59cd931972feafe73917866064c9d7b08/cljfmt/src/cljfmt/core.cljc
src/cljfmt/core.cljc:13:19: warning: namespace cljs.reader is required but never used
src/cljfmt/core.cljc:285:8: warning: unused binding sym
src/cljfmt/core.cljc:285:12: warning: unused binding alias-map
src/cljfmt/core.cljc:285:30: warning: unused binding args
linting took 77ms, errors: 0, warnings: 7
the last three warnings show up a second time in the :findings vector returned as a part of the map returned from the clojure api function run!
#2019-06-1007:50borkdude@sogaiu this is probably because a CLJC file is linted twice, once as Clj and once as Cljs. The unduplication happens in the print function, but should probably moved to an earlier stage, something I forgot when making the Clojure API#2019-06-1007:51borkdudeIf you can make a ticket so I don’t forget, I’m on mobile#2019-06-1007:52sogaiu@borkdude thanks, i will make an issue#2019-06-1008:00sogaiuhttps://github.com/borkdude/clj-kondo/issues/246#2019-06-1009:12dominicmI just ran into something that eastwood would flag as a "suspicious test" something like (t/is 5 4). Is this something clj-kondo is interested in catching?#2019-06-1009:47borkdudeSure#2019-06-1010:19sogaiulol, finally figured out the name 🙂 very nice.#2019-06-1115:43borkdudeanyone wants to test a new feature that shows unresolved symbols?#2019-06-1115:44borkdudesimple example: https://www.dropbox.com/s/8hwjal4aihae4gu/Screenshot%202019-06-11%2017.44.32.png?dl=0#2019-06-1115:46borkdudethe main goal is to eliminate false positives 🙂#2019-06-1115:53kszaboI would be glad to#2019-06-1116:00borkdude@thenonameguy would you like to run with a binary (if so, linux or mac), or the clojure version (JVM)?#2019-06-1116:03kszaboI’m using OSX, I’ve been using brew to upgrade#2019-06-1116:03kszabobut I can probably run it through clj#2019-06-1116:04borkdudethat would be fine, but here’s the MacOS binary just in case: https://3562-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.06.08-alpha-SNAPSHOT-macos-amd64.zip#2019-06-1116:04borkdudethe branch with the work in progress is called unresolved-symbols in case you want to try it with clj#2019-06-1116:04borkdudeThis is the issue, in case you want to report anything: https://github.com/borkdude/clj-kondo/issues/174#2019-06-1116:07kszabothanks, I’ll report back. It seems to work btw, I’m just seeing false positives like deftest, I’ll probably have to create a new cache for this#2019-06-1116:12borkdudedeftest should work, but you’ll have to use :require (unless I’m not understanding correctly your false positive)#2019-06-1116:13borkdudeclj-kondo doesn’t support use just like joker 🙂#2019-06-1116:31kszabo
./test/main/atlas/s3_test.clj:8:2: error: unresolved symbol use-fixtures
./test/main/atlas/s3_test.clj:9:4: error: unresolved symbol compose-fixtures
./test/main/atlas/s3_test.clj:16:2: error: unresolved symbol deftest
#2019-06-1116:31kszabo
(ns atlas.s3-test
  (:require ...
            [clojure.test :refer :all]
           ...))

(use-fixtures :once
...
#2019-06-1116:33borkdudeyeah, don’t use :refer :all (effectively the same as :use)#2019-06-1116:34borkdudehttps://github.com/bbatsov/clojure-style-guide#prefer-require-over-use#2019-06-1116:35borkdudeI could make it work, technically, but it would be a lot more complex and at the same time, I think it make sense if we abandoned use and refer all as a community. Even more so, since ClojureScript doesn’t support it, so you’re already on your way to good .cljc if you adopt this practice.#2019-06-1116:39borkdudeI should probably document this in the “opinionated” section of clj-kondo 🙂#2019-06-1116:40borkdudebut I was going to write a “how to ns” kind of linter, which is also will help you with this: https://stuartsierra.com/2016/clojure-how-to-ns.html#2019-06-1118:17nate@borkdude oh interesting, I thought the :refer :all in test code was the norm, it's the only place I've seen it and allowed it in my code#2019-06-1118:17nateI guess the alternative is to :refer what you need by name#2019-06-1120:14dominicmI use refer all extensively in dev namespaces, I think the clojure.test usage is okay also, because they're globally unique. But cljs doesn't even support it so makes life hard anyway.#2019-06-1212:12tatutare you running kondo as a CI step to check style?#2019-06-1212:13tatutIs there some ready support or should I just use the API in a clojure.test to ensure no warnings are given?#2019-06-1213:27borkdude@tatut there are already people using kondo in CI. apart from using a JVM, you can also call the binary and check the exit codes in a script for example#2019-06-1213:28borkdudehttps://github.com/borkdude/clj-kondo/#exit-codes#2019-06-1213:28borkdudeyou can also use JSON output and feed it to jq to script whatever you want, without using a JVM#2019-06-1213:49tatutrunning in JVM is easier as I don’t have to install anything on the CI machine#2019-06-1213:49tatut
(deftest lint
  (let [result (clj-kondo/run! {:lint ["src/clj" "src/cljs" "src/cljc"]})
        {:keys [error warning]} (:summary result)
        ok? (= 0 error warning)]
    (is ok? "No lint warnings")
    (when-not ok?
      (clj-kondo/print! result))))
#2019-06-1213:49tatutthat simple test seems to do the trick#2019-06-1213:50borkdudethat should work yes#2019-06-1213:50tatutnow I just have to fix all warnings 😅 …that’s the bigger issue in this large project#2019-06-1213:51borkdudeor just ignore the warnings and only count the errors. up to you 🙂#2019-06-1213:51borkdudeyou can also disable certain linters for the time being#2019-06-1213:51borkdudeusing the :config parameter#2019-06-1213:51tatutI may do an expected count and check that#2019-06-1214:01tatutok, seems just checking errors at first would be a good first step#2019-06-1214:38tatutweird, I’m getting a parse error “no conversion to symbol” in one file, but it doesn’t seem to contain anything out of the ordinary… looks like it’s coming from the reader, not kondo though#2019-06-1214:40tatutlooks like a namespaced map problem, if I have #:some.ns {:key "foo"} map in a cljs file, the parsing fails#2019-06-1214:42tatutwriting it as {:some.ns/key "foo"} works#2019-06-1214:43borkdude@tatut can you create a small repro foo.clj so when calling clj-kondo --lint foo.clj you get this problem?#2019-06-1214:45borkdudeputting only that expression in file does not reproduce it#2019-06-1214:46tatutit doesn’t seem to occur in the command line tool, only when running from my project jvm… perhaps I’m getting some wrong version from my other deps#2019-06-1214:47borkdudehm, is another library of yours also using clj-kondo? I made a patch, for this in rewrite-clj but I’m not calling that patch in the JVM version#2019-06-1214:48borkdudesee: https://github.com/xsc/rewrite-clj/issues/54#issuecomment-493038733 it’s an issue in rewrite-clj#2019-06-1214:48tatutI don’t think so, but I’ll check my deps#2019-06-1214:49borkduderequiring clj-kondo.impl.rewrite-clj-patch before calling clj-kondo should resolve the issue#2019-06-1214:53tatutthat works#2019-06-1214:53tatutthanks#2019-06-1214:57borkdudeI think I should move that require from clj-kondo.main to clj-kondo.core, but it might interfere if people already use rewrite-clj in their projects#2019-06-1215:58borkdudeI think eastwood had the same trouble with dependency clashes when people used that in their JVM so they inlined all the deps. Maybe I should do that with rewrite-clj, but I don’t know how that works license-wise#2019-06-1216:13borkdudemade an issue for this here: https://github.com/borkdude/clj-kondo/issues/254#2019-06-1217:17dominicm@tatut I'm using it with reviewdog#2019-06-1306:45Stefan@borkdude Just tried the (macOS) binary you posted above. I hope you forgive me for not going through all that has already been reported and I’ll just report my finding here:
(ns metrics-server.gitlab-fetcher
  (:require [clj-http.client :as client]
            [clojure.string :as str]
            [clojure.data.json :as json])
  (:import java.time.ZoneId
           java.time.format.DateTimeFormatter
           java.time.temporal.TemporalAdjusters
           java.time.LocalDate
           java.time.DayOfWeek))

(def zone-id (. ZoneId systemDefault))
(def formatter (. DateTimeFormatter ISO_OFFSET_DATE_TIME))
(defn date-to-string [date-time]
  (-> date-time
      (. atStartOfDay)
      (. atZone zone-id)
      (. format formatter)))
(def last-monday
  (-> (. LocalDate now)
      (. with (. TemporalAdjusters previousOrSame DayOfWeek/MONDAY))))
(def before-last-monday
  (-> last-monday
      (. with (. TemporalAdjusters previous DayOfWeek/MONDAY))))
(def before-before-last-monday
  (-> before-last-monday
      (. with (. TemporalAdjusters previous DayOfWeek/MONDAY))))
gives:
src/metrics_server/gitlab_fetcher.clj:11:17: error: unresolved symbol ZoneId
src/metrics_server/gitlab_fetcher.clj:11:24: error: unresolved symbol systemDefault
src/metrics_server/gitlab_fetcher.clj:12:19: error: unresolved symbol DateTimeFormatter
src/metrics_server/gitlab_fetcher.clj:12:37: error: unresolved symbol ISO_OFFSET_DATE_TIME
src/metrics_server/gitlab_fetcher.clj:15:10: error: unresolved symbol atStartOfDay
src/metrics_server/gitlab_fetcher.clj:16:10: error: unresolved symbol atZone
src/metrics_server/gitlab_fetcher.clj:19:10: error: unresolved symbol LocalDate
src/metrics_server/gitlab_fetcher.clj:19:20: error: unresolved symbol now
src/metrics_server/gitlab_fetcher.clj:20:10: error: unresolved symbol with
src/metrics_server/gitlab_fetcher.clj:20:18: error: unresolved symbol TemporalAdjusters
src/metrics_server/gitlab_fetcher.clj:20:36: error: unresolved symbol previousOrSame
src/metrics_server/gitlab_fetcher.clj:23:36: error: unresolved symbol previous
#2019-06-1306:47StefanAlso, this code:
(defn extract-relevant-fields [{:keys [key name]
                                [{:keys [value]}] :measures}]
  {:key key
   :name name
   :value value})
gives:
src/metrics_server/complexity.clj:7:11: error: unresolved symbol value
(Feedback on my code style is appreciated btw as I’m learning Clojure 😉)
#2019-06-1306:47StefanSimilarly:
(defn extract-relevant-fields [{{:keys [additions deletions]} :stats}]
  {:additions additions
   :deletions deletions})
gives:
src/metrics_server/churn.clj:4:15: error: unresolved symbol additions
src/metrics_server/churn.clj:5:15: error: unresolved symbol deletions
#2019-06-1307:33borkdude@stefan.van.den.oord Thanks for that. Some of those have already been solved, but there are some unknown ones, so I’ll go through them and let you know.#2019-06-1309:27borkdude@stefan.van.den.oord I believe most, if not all, errors are now resolved in this binary: https://3614-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.06.08-alpha-SNAPSHOT-macos-amd64.zip Feel free to test and report other issues at: https://github.com/borkdude/clj-kondo/issues/174#2019-06-1309:40tatutIn the CLI tool, I’m getting an “Unparsable namespace form” for:
(ns foo
  (:require [clojure.string :as str]
            #?(:cljs [cljs.reader :as reader])))
#2019-06-1309:40tatutin a .cljc file#2019-06-1309:40tatutIf I remove the reader conditional, it works#2019-06-1309:42borkdudeI can reproduce this if you lint the code as non-cljc, but as clj. but if you put this code in a .cljc file, it works#2019-06-1309:42tatutok, so it is probably my emacs config that’s broken#2019-06-1309:43borkdudeto make sure, please test from a shell: clj-kondo --lint /tmp/foo.cljc#2019-06-1309:43borkdudeclj-kondo could probably report a better error message like: reader conditional not supported in .clj file or something#2019-06-1309:45borkdudehttps://github.com/borkdude/clj-kondo/issues/256#2019-06-1309:46tatutok, I had the old custom define-flycheck-checker instead of using flycheck-clj-kondo package#2019-06-1309:46borkdudeif you’re using flycheck-clj-kondo, it should trigger this inside a .cljc file: https://github.com/borkdude/flycheck-clj-kondo/blob/master/flycheck-clj-kondo.el#L74#2019-06-1309:46borkdudeok, makes sense#2019-06-1310:27tatutis there (or should there be) a way to mark namespaces that are required for side effects in the source (not config)?#2019-06-1310:27tatutbecause I think that would be good documentation to be present in the source where the require is placed and could be used for linting purposes#2019-06-1310:28borkdude@tatut that’s what we’re trying to achieve in this discussion: https://github.com/borkdude/clj-kondo/issues/241 a convention that all tooling/linters could use#2019-06-1310:28borkdudethe voting has already started, so please read the issue and bring out your vote 🙂#2019-06-1310:29borkdudetl;dr: https://github.com/borkdude/clj-kondo/issues/241#issuecomment-500805941#2019-06-1310:33tatutvoted#2019-06-1310:38borkdude@tatut if there are many similar namespaces you want to capture in one go, you can also use a regex in the config#2019-06-1311:55Stefan@borkdude Confirmed, well done! 🎉#2019-06-1313:05borkdude@tatut another idea: https://github.com/borkdude/clj-kondo/issues/241#issuecomment-501693768#2019-06-1314:11tatutthat would be enough from a tooling stand point imo, but I kind of like forcing myself to explicitly state it (for documentation purposes)#2019-06-1314:11tatutnow the documentation is left to the comments (if any)#2019-06-1314:13tatutbut maybe less is more in this case, no need to get everyone to agree on a proper metadata style… just omit :as and :refer and it is assumed to be for side effects#2019-06-1314:14borkdude@tatut I usually use comments to document why it is required, it can be for various reasons and comments do give you the freedom to explain it how you want#2019-06-1314:15borkdudeI think I would still use comments even if there were a metadata standard#2019-06-1314:16tatutshould clj-kondo just go ahead and implement it as per your comment? with optional configuration to set it off (something like :assume-implicit-require flag)#2019-06-1314:16tatutI’m all for it, now that I think about it#2019-06-1314:17borkdudeyeah, I don’t see why not, in the next version#2019-06-1314:18borkdudeI think it makes sense as the default behavior (underreporting is better than overreporting) and an option to turn it off#2019-06-1318:48Stefan@borkdude regarding that #241 issue, probably a “stupid” question, but does it have to be namespaced? Can’t it be simply ^:implicitly_used without ns (for example)?#2019-06-1318:48borkdudethat has been discussed in the issue, some people think it should be namespaced#2019-06-1318:49borkdudejust read all the comments, hehe 😉#2019-06-1318:49StefanRight, I did but too quickly apparently, sorry 😉#2019-06-1318:49borkdudewhy the underscore though?
#2019-06-1318:51borkdudewe could also just go with ^:used maybe#2019-06-1318:51StefanAh my bad, that’s me being too new to clojure#2019-06-1318:52Stefancool I like that a lot, ^:used. Very succinct and to the point.#2019-06-1318:52borkdudeyeah#2019-06-1318:52Stefanhaving trouble keeping the underscores out of my code as well 🙂 Maybe a new linter rule? 🤪#2019-06-1318:53Stefan(prefer-kebab-to-snakes or something)#2019-06-1318:53borkdudeneh, sometimes you have to use those keys, e.g. when writing to a database table#2019-06-1318:53Stefan(even though I’m veggi so I don’t feel comfortable with either)#2019-06-1318:53borkdudethere is vegan kebab#2019-06-1318:54borkdudegood one in Berlin: https://www.angloitalianfollowus.com/who-knew-vegan-kebab-meat-exists-at-voner-berlin#2019-06-1318:55StefanI do live close to the German border, but that’s still a bit too far away I guess.#2019-06-1318:55borkdudefeel free to propose ^:used in the issue#2019-06-1318:55StefanAnyway, what was that about the database table, didn’t quite understand that?#2019-06-1318:56borkdudebecause table column names don’t support hyphens basically#2019-06-1318:57StefanAh right thanks.#2019-06-1322:07borkdudeDocumentation for an upcoming new unresolved symbols linter: https://github.com/borkdude/clj-kondo/blob/unresolved-symbols/doc/config.md#exclude-unresolved-symbols-from-being-reported If you like to take it for a test run, let me know.#2019-06-1409:42borkdudeI expect this one to have a few false positives, so I set the level to :info for now. here are some binaries in case you want to give it a pre-release try: https://github.com/borkdude/clj-kondo/issues/174#issuecomment-502042994#2019-06-1508:48tatutre: discussion on #clojure about (= 3), perhaps kondo could warn about a constantly true expression, that is likely a mistake if written like that#2019-06-1600:20sogaiu@borkdude why did you decide to use a .bat with lein as you mentioned here: https://github.com/taylorwood/clj.native-image/pull/9#issuecomment-497981891? like you, i shaved all of the yaks you seemed to, to get a deps.edn / native-image build to work w/ windows 10. was it that it seems to be less work for someone to replicate the lein / .bat approach?#2019-06-1600:39sogaiummm, actually, i thought i was using clj via compile, but no, compile resolves to compile.bat, and compile is a bash script and wouldn't have run anyway...sorry, for the noise.#2019-06-1602:15sogaiu@borkdude on a related note, regarding: https://github.com/taylorwood/clj.native-image/pull/9#issue-278357391 if the windows clj / clojure came with a standalone .exe / .com / .bat to launch the clojure-tooling implemented via powershell, do you think the lein / .bat approach would still be necessary?#2019-06-1606:55borkdude@sogaiu I ran into too many issues with a GraalVM clj wrapper that a .bat was easier#2019-06-1607:31sogaiu@borkdude hmm...it seems like it's almost there though...you also filed TDEPS-128 iiuc...that one seems to imply that a standalone launcher for the clojure-tooling would be helpful. does that seem right?#2019-06-1607:32borkdudeyeah, almost, but that wasn’t the case when I worked on it 🙂#2019-06-1607:33borkdudesee #clj-on-windows#2019-06-1607:34borkdudeI think a GraalVM executable for clj/clojure would make sense#2019-06-1608:33sogaiuwas just having similar thoughts within the last few hours :) but i don't envy the folks having to do the windows building! btw, i summarized related info here: https://gist.github.com/sogaiu/e079cd770051685c46ab24b6658effcf#2019-06-1608:38borkdudenice, thanks#2019-06-1614:50Marc O'Morainhttps://github.com/marcomorain/clojure-lint/blob/master/README.md#2019-06-1619:57lreadCool @marc-omorain! Friendly feedback: you might want to state which editor/ide this is an extension for in your github project desription and readme (Visual Studio Code, right?)#2019-06-1619:58Marc O'MorainThanks 🙏 The readme needs a LOT of work 👍#2019-06-1614:50Marc O'MorainVersion 0.1 published 🎉#2019-06-1614:50Marc O'Morainhttps://user-images.githubusercontent.com/448001/59565149-79ad7780-9047-11e9-9dcf-d8776a2b0814.png#2019-06-1615:00borkdudew00t!!! 😄 awesome!#2019-06-1615:01borkdudehow doth one install this extension?#2019-06-1615:02borkdudeI’m about to release a new version of clj-kondo. I’ll announce the extension together with it#2019-06-1615:07Marc O'MorainThere is a GUI for installing them. It’s named “Clojure-lint” (I hope!) #2019-06-1615:22Marc O'MorainI renamed the repo. Pro tip: don’t do too much typing on a MacBook Pro. #2019-06-1615:22Marc O'MorainThe keyboard is terrible. #2019-06-1615:29borkdudeSo I heard (>= 2016 models)#2019-06-1615:30borkdudeI’m preparing a new release and will announce your work together with it.#2019-06-1615:31Marc O'MorainThank you!#2019-06-1616:01borkdudeand thank you!#2019-06-1616:26borkdudeclj-kondo v2019.06.16-alpha! 🎉 major new features: - unresolved symbol detection - VSCode integration (thank you @marc-omorain !) https://github.com/borkdude/clj-kondo/releases/tag/v2019.06.16-alpha#2019-06-1618:38Marc O'Morain@borkdude about the info level: https://github.com/marcomorain/clojure-lint/blob/de399b6fba3931649113b66754ac1dbd09d6ed42/src/extension.ts#L64 I was looking for an exhaustive list of levels in the Kondo source but I couldn’t spot it. #2019-06-1618:38Marc O'MorainFixing the info issue is a letter of filling out this switch #2019-06-1618:39borkdude@marc-omorain That’s the only missing level#2019-06-1618:39Marc O'MorainThe literal string info right?#2019-06-1618:40borkdudeyes. you might want to map it to Hint or Info in VSCode, but Hint doesn’t exist in other editors always, so that’s why I chose info#2019-06-1618:42Marc O'MorainMy stretch goal is to add “suppress this” as an auto fix, so that users can click on a warning, and i would create a minimal patch to their .clj-kondo/config.edn` will be made to suppress that warning.#2019-06-1618:42borkdudeThat would be very nice.#2019-06-1618:42Marc O'Morainvscode makes it simple to add actions to each diagnostic. #2019-06-1618:42borkdudeI would have to be extra careful not to break anything in the config format, which is my stretch goal 🙂#2019-06-1618:43Marc O'MorainThe action itself is the hard part 😭#2019-06-1618:44Marc O'MorainDon’t worry about breaking the config format - extensions for vscode are simple to update, so I can react very quickly to any changes. #2019-06-1618:44borkdudedo you expect people to upgrade their extension e.g. once a week, or do they update automatically?#2019-06-1618:49Marc O'MorainIt just happens automatically #2019-06-1618:45borkdudeI was thinking of this feature: https://github.com/borkdude/clj-kondo/issues/253 so people know if something unexpected is in their config and they can upgrade, so I have more freedom to deprecate something (which I will try to avoid, but still)#2019-06-1618:45borkdude(very much inspired by the CircleCI CLI)#2019-06-1618:46borkdudeAlso, feel free to make a PR for the editor integration docs for VSCode (if I don’t beat you to it)#2019-06-1618:52Marc O'MorainThat’s really meta#2019-06-1618:52Marc O'MorainLinting the config - I love it. #2019-06-1618:53borkdudeyeah, I might also add support for linting project.clj or deps.edn 🙂#2019-06-1620:07Stefan@marc-omorain @borkdude clj-kondo in VSCode, sweet guys!!! 🎉#2019-06-1708:58genmebloghi, I'm getting false positive in case when using multiarity multimethods (didn't found an issue on github)#2019-06-1708:59genmeblog
(defmulti testmulti (fn [m & _] m))
(defmethod testmulti :some
  ([_] "zero arity")
  ([_ _] "unary")
  ([_ _ _] "binary"))
#2019-06-1708:59genmeblogerror: unsupported binding form ([_]"zero arity")#2019-06-1708:59genmebloglinter is run from lein#2019-06-1709:01borkdudeah multi-arity, yeah, thanks. I’ll make an issue for it#2019-06-1709:01borkdudedidn’t even know that was possible 🙂#2019-06-1709:03genmeblogha! 🙂 yes, and it's very convenient in some cases.#2019-06-1709:03genmeblogthanks#2019-06-1709:03genmebloganother one:#2019-06-1709:05genmeblogwhen def (or defn etc.) is emitted by macro:
(defmacro testmacro
  [symbol]
  `(def ~symbol 11))

(testmacro eleven)
I get: info: unresolved symbol eleven
#2019-06-1709:06borkdudethat can be resolved using the following config:
{:lint-as {foo/testmacro clojure.core/def}}
#2019-06-1709:06borkdudeif it uses the same syntax as def#2019-06-1709:08genmeblogunfortunately not the same syntax#2019-06-1709:08genmeblogbut ok, I can live with it#2019-06-1709:08borkdudeor a subset of the syntax#2019-06-1709:08borkdudeis this the real macro or just an example?#2019-06-1709:09genmeblogit was example, but here is the real one:#2019-06-1709:09genmebloghttps://github.com/generateme/fastmath/blob/master/src/fastmath/regression.clj#L88#2019-06-1709:09genmeblogthe macro and following macro calls#2019-06-1709:10genmeblog
src\fastmath\regression.clj:98:25: info: unresolved symbol ols
src\fastmath\regression.clj:100:25: info: unresolved symbol rls
src\fastmath\regression.clj:102:25: info: unresolved symbol lasso
src\fastmath\regression.clj:102:39: info: unresolved symbol lambda
src\fastmath\regression.clj:102:46: info: unresolved symbol tolerance
src\fastmath\regression.clj:102:56: info: unresolved symbol max-iters
src\fastmath\regression.clj:108:25: info: unresolved symbol ridge
...
#2019-06-1709:11borkdudein that case I would use the config:
{:linters {:unresolved-symbol {:exclude [(wrap-regression)]}}}
#2019-06-1709:11borkdudethat means it won’t report in a call to wrap-regression#2019-06-1709:12borkdudemore info: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-unresolved-symbols-from-being-reported#2019-06-1709:14borkdudefor vars that are introduced by this macro, you can put in an extra declare (see example of HugSQL in the linked docs)#2019-06-1709:15borkdudeor if it just gets too annoying there is a way to turn off the linter in a namespace, but I haven’t documented this yet#2019-06-1709:16genmeblogI think the best option is to use :exclude here, thank you#2019-06-1717:18mynomotoAre edn files a valid target for clj-kondo?#2019-06-1717:35borkdude@mynomoto since EDN is just a quoted clojure data structure, it could easily do that. What would be your use case for it?#2019-06-1717:38borkdudefor {:a 1 :a 2}:
$ clj-kondo --lint /tmp/foo.edn
/tmp/foo.edn:1:7: error: duplicate key :a
linting took 13ms, errors: 1, warnings: 0
but: {a 1 b 2}
$ clj-kondo --lint /tmp/foo.edn
/tmp/foo.edn:1:2: info: unresolved symbol a
/tmp/foo.edn:1:6: info: unresolved symbol b
linting took 10ms, errors: 0, warnings: 0
so it needs to read it as a quoted value, which would just be a small change
#2019-06-1717:55borkdude@mynomoto feel free to post a Github issue about it#2019-06-1717:59mynomotoI did open a deps.edn file and clj-kondo warnings were all over it so I wanted to know if this was expected.#2019-06-1717:59borkdudewhich editor integration are you using?#2019-06-1718:01borkdudeI think it makes sense to support this#2019-06-1718:02borkdudebut as of now, the editor integration should not lint .edn files. so I wonder which one you’re using#2019-06-1718:05mynomotoAle on vim.#2019-06-1718:06mynomotoAle works by filetype and I set edn as clojure because of syntax highlight#2019-06-1718:06borkdudeah I see#2019-06-1718:07borkdudeI’m not in control of that plugin. Does ale send the code over stdin or via the filesystem?#2019-06-1718:08borkdudein other words: is there any way clj-kondo can see it’s dealing with a .edn file?#2019-06-1718:13borkdude@mynomoto I’ll just implement it and let you know as soon as it’s there: https://github.com/borkdude/clj-kondo/issues/270#2019-06-1721:00borkdude@mynomoto: https://github.com/borkdude/clj-kondo/issues/270#issuecomment-502848946#2019-06-1812:04souenzzoFirst, tnks for kondo. Then a issue report 🙂 echo '(ns f (:require [clojure.string :as s])) (defn f [{::s/keys [x]}] x)' | clj-kondo Will report <stdin>:1:18: warning: namespace clojure.string is required but never used#2019-06-1812:31borkdude@souenzzo https://github.com/borkdude/clj-kondo/issues/273#2019-06-1812:43souenzzoThere is too many warns in my project. Most of then good/useful, but some odd/wrong. I will implement/report it later.#2019-06-1812:54borkdude@souenzzo thank you. specific examples like the ones you posted are helpful. many times you can prevent warnings using config: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#2019-06-2112:01Marc O'Morainhere is a slightly interesting case: I deleted some braces from the end of an edn file:
$ clj-kondo --lint  src/test/.clj-kondo/config.edn
src/test/.clj-kondo/config.edn:0:0: error: can't parse src/test/.clj-kondo/config.edn, Unexpected EOF. [at line 5, column 1]
#2019-06-2112:02Marc O'MorainThe error is flagged as row/col 0:0, but the error message says 5:1#2019-06-2112:02Marc O'Morain
{:linters {


    :invalid-arity {:level :error
#2019-06-2112:03Marc O'MorainThis is somewhere were I really dislike the Clojure error message - it focuses on the wrong thing.#2019-06-2112:03Marc O'Morain“Unexpected EOF” should be “unclosed { at line 4 column 21"#2019-06-2112:43borkdudeyeah, good point. I though I parsed that exception somewhere and turned it into the correct locations, but it might not work everywhere. I’ll make an issue#2019-06-2112:45borkdudehttps://github.com/borkdude/clj-kondo/issues/286 I’m not sure if “unclosed” will work, because this exception comes from tools.reader#2019-06-2113:05borkdude@tsulej https://github.com/borkdude/clj-kondo/issues/269#issuecomment-503949932#2019-06-2113:06genmeblogThank you!#2019-06-2113:06borkdudenot sure if you wanted to test it, in that case let me know if the linux binary is sufficient#2019-06-2319:34genmeblog@borkdude just checked multiarity multimethods - works for me, thanks!#2019-06-2319:35borkdudealright, thanks for the feedback#2019-06-2320:55borkdudeclj-kondo v2019.06.23-alpha! 🎉 new features: - lint .edn files - syntax checking for clojure.spec/fdef - spacemacs docs https://github.com/borkdude/clj-kondo/releases/tag/v2019.06.23-alpha#2019-06-2320:58borkdude@marc-omorain I think it’s safe to update your vscode plugin now with the --cache option again#2019-06-2323:36oskarkvIt seems the install script doesn't work for me on Linux.
~ » curl -sO 
chmod +x install-clj-kondo
./install-clj-kondo
Downloading 
------------------------------------------------------------
~ » ll /usr/local/bin | grep kondo  
------------------------------------------------------------
~ »    
#2019-06-2409:03borkdude@oskarkv I think it might have to do with permissions. I changed some things now, but I think if it's a permission error you'll have to install with with root or use a different install dir: ./install-clj-kondo --dir ~/bin#2019-06-2707:18jumarI'm getting clj-kondo-edn is not a valid syntax checker error when starting spacemacs. Does somebody know what's going on?#2019-06-2707:26borkdude@jumar please upgrade the flycheck-clj-kondo package#2019-06-2707:29borkdudehttps://github.com/borkdude/flycheck-clj-kondo/blob/master/flycheck-clj-kondo.el#L75#2019-06-2707:29jumar@borkdude that worked like a charm - thanks!#2019-06-2707:30borkdude👍#2019-06-2707:30jumarbtw. would it be possible to automatically check :args specs for functions or is that by definition impossible to do with clj-kondo?#2019-06-2707:31borkdudein a limited fashion, it could be possible, e.g. when you use literals as arguments, but it only would go so far. I have an issue for this#2019-06-2707:33jumarwhich one is that?#2019-06-2707:33jumarAh I see - I guess this one 🙂 https://github.com/borkdude/clj-kondo/issues/23#2019-06-2707:34borkduderight#2019-06-2707:34jumarGreat, thanks for all the great work so far and super-fast support 🙂#2019-06-2707:35borkdude👍#2019-06-2708:07tatutI guess other linters check for this so it may not be a priority, but I still find the occasional misplaced docstring in my code, would be nice to warn about that#2019-06-2708:07tatutor more generally, superfluous discarded constant expressions#2019-06-2708:08tatut(defn foo [bar] "misplaced docstring" ...code...)#2019-06-2708:12borkdude@tatut I think that overlaps with this issue. feel free to add it: https://github.com/borkdude/clj-kondo/issues/259 when I'm adding the enhancement label, it will probably be implemented. I can't promise when 🙂#2019-06-2708:13tatutI think, the more general case isn’t overlapping… having constant expressions that are discarded#2019-06-2708:13tatutthat we know can’t be for side effects#2019-06-2708:14tatutlike (defn foo [] 1 2 3) the 1 and 2 are discarded and can’t side effect#2019-06-2708:14borkdudemissing docstring is probably something I will turn off by default, since not all people require this and it's not "wrong" to leave them out (arguably). but a misplaced docstring is something I will probably turn on by default#2019-06-2708:15borkdudediscarding "useless" constant values is indeed a more general topic and doesn't only concern def and defn so that deserves a separate issue#2019-06-2708:18borkdudemaybe make two different issues for those things then#2019-06-2708:18tatutthanks for your work on clj-kondo, it has become invaluable in the short time I’ve used it 🙂#2019-06-2708:18borkdudecool, no problem 🙂#2019-06-2806:41Stefan@borkdude Pull request came through, clj-kondo is on clojure-toolbox now 🙂#2019-06-2806:41borkdudeAwesome, thanks!#2019-06-2806:41StefanWelcome! 🙂#2019-06-2809:37dharrigan@borkdude I've added clj-kondo to the Arch User Repository 🙂#2019-06-2809:38dharriganhttps://aur.archlinux.org/packages/clj-kondo-bin/#2019-06-2809:49borkdudew000t, thank you!#2019-06-2809:50borkdude@dharrigan feel free to send a PR with install instructions for this page: https://github.com/borkdude/clj-kondo/blob/master/doc/install.md#2019-06-2809:52dharrigannp#2019-06-2810:12dharrigandone, PR ready.#2019-06-2810:20borkdudemerged, thanks!#2019-06-2810:32dharrigannp#2019-06-2916:15borkdudeclj-kondo v2019.06.29-alpha! 🎉 https://github.com/borkdude/clj-kondo/releases/tag/v2019.06.29-alpha#2019-07-0112:21tatutno that the vote on #241 is over, I think we really should have gone with ^:sparks-joy annotation to keep it from being removed 😉#2019-07-0112:23borkdudelol 🙂#2019-07-0508:36borkdudeclj-kondo v2019.07.05-alpha! 🍻 Features: faster parsing, misplaced docstrings https://github.com/borkdude/clj-kondo/releases/tag/v2019.07.05-alpha#2019-07-0508:40dharriganarch package also updated 🙂#2019-07-0508:42borkdudethanks, that was fast 🙂#2019-07-0508:43borkdudeis that arch package code in a git repo somewhere?#2019-07-0508:43dharriganHave a look...#2019-07-0508:44dharriganhttps://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=clj-kondo-bin#2019-07-0508:44dharriganAll I've done is provide a PKGBUILD which pulls down your release and does the work for making it suitable for isntalling on arch.#2019-07-0508:44dharriganIt's very very very similar to FreeBSD ports#2019-07-0508:44dharriganbasically, I find it a joy to use, so much easier than the dance one has to do for debian based distros#2019-07-0508:45borkdudenice. I've been looking into making a package for ubuntu/debian, but this looks much simpler 😅#2019-07-0508:45borkdudemore like brew#2019-07-0508:45dharriganit's a bazillion percent easier#2019-07-0508:49dharriganhttps://michael.stapelberg.ch/posts/2016-11-25-build-tools/#2019-07-0508:49dharriganfrom an ex-maintainer#2019-07-0508:49dharriganbtw, I'm not saying that debian is bad (it was the first distro I used), just that packaging can be hard.#2019-07-0508:52borkdudeI think I'll close that issue then 😛#2019-07-0509:04sogaiufwiw, that's one of the good reasons to use an arch-derived distribution 🙂#2019-07-0509:09borkdudeI might consider arch if I go off MacOS one day#2019-07-0509:09borkdudefor server, I still run Debian#2019-07-0509:10borkdudeNixOS also seems interesting, I know someone who is a true fan and has his new laptop up and running really fast with his setup#2019-07-0509:13dharriganLooks good!#2019-07-0509:13dharriganDiversity in the ecosystem is good#2019-07-0509:17borkdudeIt seems at Juxt they are also using Arch a lot#2019-07-0509:19dharriganI really like Arch. I like that I know precisely what I've setup and I like knowing it's a rolling release.#2019-07-0509:19dharrigannot waiting 6 months for upgrades to stuff.#2019-07-0509:19dharriganhas everything I need for a distro#2019-07-0509:25borkdudeyeah, nixos seems to have quite a learning curve, arch is looking attractive to me#2019-07-0509:26dharriganThe arch wiki is one of the reasons too. It's very comprehensive.#2019-07-0509:28sogaiui used to use nixos -- if it weren't for the odd programming language you have to learn i might still be 🙂#2019-07-0509:29sogaiuyes, the arch wiki is quite the resource.#2019-07-0509:29sogaiuyou don't have to start with arch itself though -- it's easier to try manjaro and get a fair bit of the benefit.#2019-07-0509:31borkdudewhat's manjaro then compared to arch?#2019-07-0509:32sogaiuroughly, think of ubuntu is to debian as manjaro is to arch#2019-07-0509:33sogaiumuch easier to set up and most of the packages from arch work on manjaro (at least the user-contributed ones at aur i've been using fine)#2019-07-0509:34sogaiuaur == https://aur.archlinux.org/#2019-07-0509:34sogaiueasy enough to try in a vm 🙂#2019-07-0509:37borkdudeis aur also possible on other distros like ubuntu, just like you can install linuxbrew?#2019-07-0509:39sogaiunot that i'm aware of#2019-07-0509:39sogaiui think portions of nixos (nixpkgs, i think) is/are though#2019-07-0509:39sogaiuat least that used to be true#2019-07-0513:33practicalli-john@borkdude have you considered using https://snapcraft.io/ to package clj-kondo for multiple Linux distributions? Looks very simple. Its the approach that Heroku CLI, VS Code and Slack take. The package is self-contained, so you are not installing into the operating system, keeping a nice clean separation (I currently install clj-kondo in $HOME/bin rather than in the OS file system)#2019-07-0513:33borkdudeI haven't considered it, but thanks for mentioning it, I'll take a look#2019-07-0513:36sogaiui note with interest, the criticism section of the wikipedia article for snappy, as well as a couple of other alternatives that sound similar somewhat there.#2019-07-0513:50sogaiu@borkdude btw, any further thoughts on: https://github.com/borkdude/clj-kondo/issues/234 ?#2019-07-0513:52borkdudestill on the list, will implement it, but not sure when it will be released#2019-07-0513:53borkdude@jr0cket does it matter which base image I choose? for Docker I normally try alpine for small size. does this matter with snap?#2019-07-0513:55sogaiuthanks - do you think finding definitions would be doable too? my impression from looking at clj-kondo's source was that it might be doable without too much work.#2019-07-0513:56borkdudeyeah, I think so 🙂#2019-07-0513:57sogaiulooking forward to it 🙂#2019-07-0513:58borkdude@sogaiu fwiw, now I use ag for that#2019-07-0514:00sogaiui am a heavy user of ag too -- it's just that if clj-kondo can do it, standalone non-repl dependent editor tooling that is light and fast may be doable for "jump-to-definition" functionality 🙂#2019-07-0514:02lreadthis here thingy? https://github.com/ggreer/the_silver_searcher#2019-07-0514:03sogaiuyep#2019-07-0514:03borkdudeyep#2019-07-0514:03borkdudeit's basically grep, but faster#2019-07-0514:04lreadhuh, I think today is turning out to be a good day to learn new things#2019-07-0514:09borkdude@jr0cket or anyone else using snap: https://snapcraft.io/clj-kondo welcome to try it out and report success or problems#2019-07-0516:32practicalli-johnWill try using the snap on my other laptop tomorrow as a clean install (just installed latest alpha of clj-kondo on current laptop - it works great)#2019-07-0516:33borkdudeThank you 🙂#2019-07-0516:33borkdudedid you install the current with the install script?#2019-07-0516:33borkdudeor just manually?#2019-07-0518:58practicalli-johnManually. Initially I installed with the clj-kondo-install script, to the default /user/local/bin. With the new version today, I just unzipped the executable to my $HOME/bin, which is on the system PATH before /user/local/bin. I try avoid putting things on the OS file system if its not in a debian package.#2019-07-0518:59borkdudemake sense#2019-07-0519:01practicalli-john$HOME/bin is great for multiple versions or things that have a lot of new versions I want to try. I usually use a symlink if I think I need to switch between versions often.#2019-07-0519:01borkdudeI do something similar#2019-07-0821:41borkdudeI have experimented with snap some more. It seems I do need the --classic confinement to be able to read files and write into the .cache dir, so it might take a while#2019-07-0822:41practicalli-johnGood to know there are some safety checks, you could be doing anything 🙂#2019-07-0908:19borkdudeyeah, in the strict confinement, the root can connect the plug home so the tools can read/write your home directory, but they made an exception for "hidden" directories, starting with a dot. That's why clj-kondo cannot even read its own config dir, so that's a little too strict#2019-07-0514:21lread36 minute turn around time from suggestion to release! #2019-07-0514:43dharriganfaster than the silver searcher#2019-07-0514:43dharriganhttps://github.com/BurntSushi/ripgrep#2019-07-0514:44dharrigan#2019-07-0514:44dharriganthat coupled with FZF == power!!!!!#2019-07-0515:01StefanOooh nice tip, thanks!#2019-07-0515:08mynomotoripgrep is amazingly fast#2019-07-0516:30practicalli-johnRipgrep is the default search tool for Spacemacs (if you have ripgrep installed), otherwise it looks for silver surfer (ag) and then grep... Ripgrep is very fast.#2019-07-0603:29sogaiuah, i didn't know ripgrep had windows support too. nice. thanks all for chatting about it 🙂#2019-07-0808:32borkdude@jr0cket I had first published the snap with confinement --dev-mode but now I used --classic.#2019-07-0808:32borkdudeIt seems they put it in review now because of this: https://dashboard.snapcraft.io/snaps/clj-kondo/revisions/2/#2019-07-0810:57borkdudefeel free to vote: https://twitter.com/borkdude/status/1147975431343222785#2019-07-0811:53sogaiuboth options are improvements over the one that used 2 parens 🙂#2019-07-0812:06dharriganFirst one#2019-07-0812:06dharriganclj-kondo.svg#2019-07-0812:07borkdudethanks#2019-07-0822:23lreadI am digging into clj-kondo warnings for rewrite-clj cljc project I am working on. Love it!#2019-07-0822:25lreadI am thinking clj-kondo might be seeing this as zero arg fn?
(defn parse-next
  [#?(:cljs ^not-native reader :default reader)]
  (reader/read-with-meta reader parse-next*))
#2019-07-0822:47lreadA similar example, clj-kondo is seeing this as a 1 arg fn:
(defn- string-of?
  [#?(:clj ^String s :default s) pred]
  (and s
       (string? s)
       (pos? (count s))
       (every? pred s)))
#2019-07-0906:52borkdude@lee I think you’re the first clj-kondo user that uses :default, it’s currently not recognized. I’ll make a fix, thanks #2019-07-0906:52borkdudeIf you include :cljs in the last example it’ll probably work#2019-07-0907:10sogaiufwiw, it's nice to use :default because of the potential for clojure clr support#2019-07-0907:17borkdudeyes, it should be supported#2019-07-0907:39sogaiugood to hear 🙂#2019-07-0908:12borkdude@lee which OS are you using?#2019-07-0908:14borkdudehere is a fix for linux: https://4381-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.07.06-alpha-SNAPSHOT-linux-amd64.zip and here is one for macOS: https://4379-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.07.06-alpha-SNAPSHOT-macos-amd64.zip#2019-07-0911:19lreadI got that :default idea from our very own @sogaiu. I am not handling clojure-clr yet, but it is a step in that direction.#2019-07-0911:20lreadI am on macOS, and thanks! You are speedy!#2019-07-0911:23lreadBTW your clj-kondo logo is pretty awesome. It tells the story and spirit of the tool in smile inducing way.#2019-07-0911:24borkdudeI think I recommended :default to you too in the rewrite-clj channel 🙂#2019-07-0911:24borkdudethanks, it was the result of a nice interaction with nikitonsky on twitter#2019-07-0911:37lreadwell, my continued thanks to you both simple_smile #2019-07-0911:40borkdudeor maybe I recommended it to someone else, but I vaguely remember this for the same reason as sogaiu mentions: if more targets are added, you're already future proof#2019-07-0911:50lreadyeah it’s a good tip!#2019-07-0913:28lreadjust tried snapshot build you provided, works like a charm, thank you!#2019-07-0913:29borkdudethanks for reporting and testing#2019-07-0913:51lreadrewrite-clj has maybe uncovered another clj-kondo issue. In a macro, a variable only referenced with quote unquote is reported as unused. For example, clj-kondo gives an unused binding warning for new-meta for the following:
(defmacro import-fn
  "Given a function in another namespace, defines a function with the
   same name in the current namespace.  Argument lists, doc-strings,
   and original line-numbers are preserved."
  [src-sym target-name target-meta]
  (let [vr (resolve-sym src-sym)
        m (meta vr)
        m (resolve-fn-location m)
        new-meta (dissoc target-meta :name)
        protocol (:protocol m)]
    (when (:macro m)
      (throw (ex-info "potemkin clj cannot import-fn on a macro" {:symbol src-sym})))
    `(do
       (def ~(with-meta target-name (if protocol {:protocol protocol} {})) (deref ~vr))
       (alter-meta! (var ~target-name) merge '~new-meta)
       ~vr)))
#2019-07-0913:55borkdudehmm, I see#2019-07-0913:55borkdudewould '~new-meta be the same as (quote ~new-meta)?#2019-07-0913:56borkdudemight work as a workaround, nevertheless, it's a false positive#2019-07-0914:00lreadyes, that work-around does the trick.#2019-07-0914:05lreaddo you want a git issue for this one?#2019-07-0914:19borkdudesure!#2019-07-0914:20borkduderight now clj-kondo doesn't analyze everything that follows a literal quote for usages, but in backticks this apparently doesn't hold#2019-07-0914:40lreadwill do!#2019-07-0914:43lreadI have another one for you. When including a macro like so in a cljc source:
(ns forborkdude
  #?(:cljs (:require-macros [forborkdude :refer [my-macro]])))

#?(:clj
   (defmacro my-macro[x]
     `(str "hello there, " ~x)))

(my-macro "borkdude")
clj-kondo reports my-macro as an unresolved symbol.
#2019-07-0914:52borkdude@lee what's the reason you're only defining it for :clj?#2019-07-0914:52borkdudeyour lib doesn't support self-hosted CLJS?#2019-07-0914:53lreadhmmm…#2019-07-0914:53borkdudenonetheless, it's a false positive that kondo should support#2019-07-0914:55lreadself-hosted CLJS is on my todo list… still need to learn details on how macros work there.#2019-07-0914:56borkdudefor self-hosted you'll need to remove the :clj conditional and then it should just work, unless you're using JVM specific things#2019-07-0914:57lreadwell that’s cool.#2019-07-0914:58lreadi can git issue this one too if you’d like#2019-07-0914:58borkdudeyes please!#2019-07-0915:17lreaddone!#2019-07-0915:21borkdudethank you ❤️#2019-07-0915:33lreadand thank you too for all your help and a linter that sparks joy#2019-07-0915:37borkdude@lee here's a fix for the self-require issue: https://4388-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.07.06-alpha-SNAPSHOT-macos-amd64.zip#2019-07-0918:37lreadthanks, that fixed the issue.#2019-07-0919:07lreadok, no more clj-kondo warnings under my src tree, time to move on to test!#2019-07-0919:15lreadrewrite-clj tests make heavy use of the clojure.test.are macro. Does clj-kondo want to do any linting on these? Contrived silly example:
(deftest t-for-borkdude
  (are [?a ?b]
      (is (= ?a (dec ?b)))
    1 2
    10 11
    14 15))
Currently clj-kondo informs me that ?a and ?b are unresolved symbols.
#2019-07-0919:44lreadOh wait, your default config has some handling for are: https://github.com/borkdude/clj-kondo/blob/67966d2c38a813c909371f5c08b64a742c6806e4/src/clj_kondo/impl/config.clj#L44#2019-07-0919:46lreadah… it is missing the cljs.test variant.#2019-07-0919:50lreadIf I add the following to my .clj-kondo/config.edn my cljc files no longer produce warnings:
{:linters
 {:unresolved-symbol
  {:exclude [(cljs.test/are)
             (cljs.test/is [thrown-with-msg?])]}}}
#2019-07-0919:52lreadI’ll git issue this one.#2019-07-0919:58borkdude@lee Not yet, thanks for the git#2019-07-0920:10lreadadded issue https://github.com/borkdude/clj-kondo/issues/335#2019-07-0920:48lreadI frankly don’t much about them yet, but rewrite-clj uses defspec in some tests. I don’t think clj-kondo handles these puppies yet?
#2019-07-0920:55borkdudewhat's defspec?#2019-07-0920:55lreadhmmm… I assumed it was a common thingy. I’ll get back to you.#2019-07-0920:56lreadhttps://clojure.github.io/test.check/clojure.test.check.clojure-test.html#var-defspec#2019-07-0920:58lreadI’ve not learned about test.check yet.#2019-07-0920:58borkdudeyou can use :lint-as for this to treat it as clojure.core/def#2019-07-0920:58lreadthanks I shall try that!#2019-07-0920:59borkdude{:lint-as {foo.bar/defspec clojure.core/def}}#2019-07-0921:05lreadthat worked, thank you!#2019-07-0921:36borkdudeUpdated docs for the snap package manager. You might want to try it: https://github.com/borkdude/clj-kondo/blob/master/doc/install.md#snap-linux (cc @jr0cket)#2019-07-1000:02fiddlerwoaroofIt'd be interesting if clj-kondo could interpret metadata declarations and use them to control linting#2019-07-1002:56lreadI am running both joker and clj-kondo in spacemacs. There certainly is overlap between the two tools, and I am thinking of dropping joker. Do you think I will regret dropping joker?#2019-07-1006:42borkdude@fiddlerwoaroof do you have an example?#2019-07-1016:18fiddlerwoaroofIf I have something like this:
(defn fun {:ignore-vars '[arg1 arg2]} 
  [arg1 arg2])
clj-kondo could supress warnings about arg1 and arg2 being unused.
#2019-07-1006:44borkdude@lee I use a small wrapper script that turns off some joker features and I use that together with clj-kondo. I could share it if you want#2019-07-1010:13lreadyes please @borkdude!#2019-07-1011:04borkdude@lee:
#!/usr/bin/env bash

## turn off some joker features, so I can test clj-kondo better

/usr/local/bin/joker "
#2019-07-1011:07borkdudeI've put that in ~/Dropbox/bin and put that on the path before /usr/local/bin#2019-07-1011:07borkdudein emacs I use both clj-kondo and joker with flycheck#2019-07-1011:07borkdudemaybe I should put this in a blog 😉#2019-07-1011:31lreadthanks! it might go well as a side-note in your docs where you talk about joker: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#2019-07-1011:32borkdudewell, it's kind of subjective what you want to suppress from joker, so it's not general advice, just how I happen to use it#2019-07-1011:33borkdudebtw, do you use emacs or some other editor?#2019-07-1011:43borkdude@lee I'm fixing the quote-unquote bug right now. It results in a few less false positive while linting CLJS. e.g. here: https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/spec/alpha.cljc#L179 nice!#2019-07-1011:48lreadsweet! #2019-07-1011:49lreadI am using spacemacs#2019-07-1011:52lreadSo maybe a blog post is better then. Personally I am only interested in heating from joker when it sees something that clj-kondo cannot see.#2019-07-1011:53borkdudeHave you seen: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#spacemacs#2019-07-1011:54borkdudeWith joker you might also be able to use its config to turn some things off, but I found a wrapper script to be more flexible#2019-07-1011:54borkdudeand if I really want vanilla joker, I do: /usr/local/bin/joker#2019-07-1011:55borkdude@lee Here's a fix for MacOS for the quote-unquote issue: https://4422-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.07.06-alpha-SNAPSHOT-macos-amd64.zip#2019-07-1011:57lreadthanks, I shall try it shortly!#2019-07-1011:58lreadyes your spacemacs docs (with joker) are what my current setup is based on#2019-07-1011:58lreadI think I prefer the wrapper script as well#2019-07-1011:58borkdude👍#2019-07-1011:59borkdudemaybe you could blog about it then 😉#2019-07-1012:00borkdudekidding#2019-07-1012:02lreadmaybe I should setup a blog someday! #2019-07-1012:04lreadso, that blog, if someone were to write it, might highlight what joker brings in addition to clj-kondo. As a newb, I’m currently unclear on that.#2019-07-1012:05borkdudeI think the most notable difference today is that joker is able to do some basic type checking on literals like (inc "string")#2019-07-1012:05borkdudebut I want to get that in clj-kondo as well#2019-07-1012:06borkdudeI'd say just use them both and turn off the overlapping parts with a script#2019-07-1012:06lreadso if you add that feature first, maybe the blog post advice on joker would change.#2019-07-1012:07borkdudetrue that#2019-07-1012:07borkdudemight want to hold off a bit then#2019-07-1013:08lreadjust tried quote-unquote fix, works great, thanks!#2019-07-1013:09lreadalso joker is now much quieter thanks to your wrapper script. :thumbsup:#2019-07-1013:50lread@borkdude, cljs compiler has a :fn-deprecated warning. I fail my build if I use anything deprecated - except when I am calling my own deprecated fn from a deprecated function or am testing my own deprecated fns. My build is currently awkward/brittle when handling these exceptions. Do you have plans to add deprecated checking to clj-kondo?#2019-07-1015:22borkdude@lee sure! can you post an issue with some examples? would be happy to support it#2019-07-1015:41lreadcool! I think the clj only folks will probably find it useful too. I’ll try to get a git issue up today.#2019-07-1016:18fiddlerwoaroofIf I have something like this:
(defn fun {:ignore-vars '[arg1 arg2]} 
  [arg1 arg2])
clj-kondo could supress warnings about arg1 and arg2 being unused.
#2019-07-1016:33borkdude@fiddlerwoaroof the way to solve that right now is to start the argument names with an underscore: (fn [_arg1 _arg2])#2019-07-1016:34borkdude@lee fix for clojure.test is + are: https://4435-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.07.06-alpha-SNAPSHOT-macos-amd64.zip#2019-07-1016:36fiddlerwoaroof@borkdude cool, the other use I thought of was for describing the syntax of custom macros. #2019-07-1016:40borkdudecan you give an example? note that the config already supports a bunch of things for custom macros: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#lint-a-custom-macro-like-a-built-in-macro https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-unresolved-symbols-from-being-reported#2019-07-1016:49fiddlerwoaroofOne thought would be something like this:
(defmacro deftest
  {:clj-kondo/binds-globally '[test-name]}
  [test-name & cases])
#2019-07-1016:51fiddlerwoaroofThen, when the macro is used, clj-kondo could add the value of test-name to its dictionary of available names. I understand a lot of this can be done in the config file but I'd rather have the option to declare this stuff inline.#2019-07-1017:28borkdudeThat is a little bit complicated, since clj-kondo might lint files where your deftest macro is used, but it doesn't yet know about the macro itself. E.g. when using editor integration, you only lint one file at a time#2019-07-1017:39fiddlerwoaroofSure, but there's already something like that with the --cache options?#2019-07-1017:40fiddlerwoaroofe.g., IIUC, arity errors don't work correctly without a cache#2019-07-1017:55borkdudeclj-kondo can function correctly without a cache, but will just underreport arity errors when it doesn't know the arity of a called function with your example clj-kondo will overreport without a cache, something which I think is undesirable and hard to debug when users will report those false positives#2019-07-1017:56borkdudein general, it's best to err on the side of false negatives#2019-07-1017:57borkdudealso, so far my impression is that most users don't like tool-specific annotations inside their code. I have considered it at one point for e.g. https://github.com/borkdude/clj-kondo/issues/241, but when a solution arose that required no changes to the code, that was the preferred option#2019-07-1017:59borkdudeI'm not completely dismissing the idea and I've also experimented with a namespace local config for some linters#2019-07-1018:00borkdudebut so far doing it via the config file is the preferred and most simple way#2019-07-1018:03borkdudefor testing, I sometimes use this:
(ns ^{:clj-kondo/config '{:lint-as {foo/foo clojure.core/def}}} foo)
(defmacro foo [_name & _body] ,,,)
(foo x)
(x 1)
it works, but it's undocumented
#2019-07-1018:40lreadhey there @borkdude, I submitted the my first clj-kondo feature request https://github.com/borkdude/clj-kondo/issues/338#2019-07-1018:44borkdudethanks!#2019-07-1020:52lreadNow linting my project on circleci with clj-kondo! Fun stuff!#2019-07-1102:39bedersJust added clj-kondo to my project. I found so much cruft and it was a joy removing it. Thank you for this linter!#2019-07-1210:13borkdudeif anyone wants a free clj-kondo sticker at Heart of Clojure or ClojuTRE... https://twitter.com/borkdude/status/1149620184304406531#2019-07-1510:06borkdudeI've pushed a new version of clj-kondo to master which supports detecting deprecated var usage. Might want to give it a try before next release.#2019-07-1721:40borkdudeclj-kondo v2019.07.17-alpha! 🥳 Features: (not (empty? ...)) -> seq, deprecated var usage https://github.com/borkdude/clj-kondo/releases/tag/v2019.07.17-alpha#2019-07-1809:52borkdudeposted a link to HN... https://news.ycombinator.com/item?id=20468070 🙂#2019-07-1809:52dharriganUpdated on Arch btw 🙂#2019-07-1809:52borkdudethank you!#2019-07-1810:01lreadawesome! I can now delete my custom and brittle cljs build step that checks for deprecated calls! partywombat #2019-07-2012:18borkdudeI can send clj-kondo stickers around the world for just 2 euros. If you want one by mail, just let me know and we can work something out 🙂. https://twitter.com/borkdude/status/1149620184304406531#2019-07-2121:29euccastroclj-kondo gives me unresolved symbol warnings for symbols I'm trying to define with compojure.core/defroutes. how do I teach clj-kondo that defroutes is actually defining a var, so it knows not to warn either at the point of definition nor in subsequent usages of the var? same with rum.core/defc and many others#2019-07-2121:32borkdude@euccastro https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#lint-a-custom-macro-like-a-built-in-macro#2019-07-2121:32borkdudeThat would be something like {:lint-as {compojure.core/defroutes clojure.core/def}}#2019-07-2121:37euccastrothanks @borkdude! alas, I tried just that and it didn't seem to work. I'm using spacemacs; maybe that sets some config in --config that overrides my ~/.clj-kondo/config.edn?#2019-07-2121:39borkdude@euccastro clj-kondo picks the first .clj-kondo directory up from your working directory, so maybe there is another one in the way?#2019-07-2121:39borkdudeif you can post a small snippet of your code, I could test it#2019-07-2121:39borkdude--config doesn't get in the way of .clj-kondo/config.edn, those are merged#2019-07-2121:39euccastrothanks! yes, I had a project-specific .clj-kondo that was being picked up instead. copying the config.edn there worked!#2019-07-2121:42euccastroso I guess my mistake was trying to set this globally in a $(HOME)/.clj-kondo#2019-07-2121:43borkdudeit's best to have a project-specific clj-kondo directory I think, this way you can avoid namespace conflicts, as this directory is also used to populate a cache#2019-07-2121:43euccastroI agree, I just misread the setup instructions#2019-07-2121:43borkdudenp#2019-07-2306:03sogaiuis there a way to get clj-kondo to ignore the content of (comment ...) ?#2019-07-2306:53borkdude@sogaiu yes: https://github.com/borkdude/clj-kondo/blob/cf03aa660f65d6233cbfb7cd2934b6fc9c2efa5a/src/clj_kondo/impl/config.clj#L10#2019-07-2307:17sogaiuthanks!#2019-07-2308:36Marc O'Morain> if kondo doesn't catch this already - we should suggest to kondo that it'd be a neat lint This was from a PR at CircleCI. The last line of a function was retuning (ex-info ...) rather that throwing it. #2019-07-2309:08borkdude@marc-omorain returning an ex-info is valid, so it's hard to say when it's not intended?#2019-07-2310:29Marc O'MorainThat’s true.#2019-07-2314:07borkdudeI'll be at @heartofclojure. If you want to know more about clj-kondo, how to configure it, or want to bounce around ideas, feel free to approach me. Could also organize an event https://activities.heartofclojure.eu if there is interest, agenda to be determined on the spot.#2019-07-2419:25borkdudeclj-kondo v2019.07.24-alpha! 🧹 detection of unused referred vars and more https://github.com/borkdude/clj-kondo/releases/tag/v2019.07.24-alpha#2019-07-2512:08tianshuhow about the progress for spec checking?#2019-07-2512:10borkdudenothing there yet#2019-07-2512:11borkdudeif you want something like that right now, you might want to give #spectrum a go#2019-07-2513:04tianshuI think spectrum is adding a lot to the spec#2019-07-2513:05borkdudeI'm still planning to support some spec related stuff, but note that it will always be more limited than run-time checking#2019-07-2513:09tianshuI think just checking about the type is enough, e.g string?, number?#2019-07-2514:01borkdudejoker also has support for this, e.g. when you do (inc "s") it will give a warning. I plan to support this, it's just something I will get to eventually#2019-07-2515:09dharriganarch package updated to v2019.07.24-alpha#2019-07-2515:10borkdudethank you!#2019-07-2515:54CrispinHey! Does clj-kondo do linting of cljs and cljc files?#2019-07-2515:56borkdudeyes, also .edn#2019-07-2515:57Crispin😍#2019-07-2515:57Crispinhow long has it been around for? I remember looking for a linter that would show me unused requires that worked with cljs and cljc a year or so ago and found nothing#2019-07-2515:58Crispindid I just not find this? Or is it fairly new?#2019-07-2515:58borkdudeclj-kondo is 4 months old now#2019-07-2515:58borkdudethere's also joker which can find unused requires, which has been around for 2 years or longer#2019-07-2516:00CrispinAwesome! I will try it#2019-07-2516:00CrispinI think I found joker but was put off by the fact it wasn't written in clojure#2019-07-2516:01Crispinseemed strange to me that for a task that required reading lisp, you wouldn't use the lisp itself, seeing as lisp seperates the reader and evaluator.#2019-07-2516:02Crispintheres the startup time problem, of course. But that's not a big concern for me as this would be part of a CI/CD pipeline#2019-07-2516:02Crispinhow is clj-kondo's startup time?#2019-07-2516:03borkdudejoker is an attempt to make scripting in clojure faster. I think that's the reason it was implemented in Go, because of the startup time. but clj-kondo leverages GraalVM which results also in fast start up time. an average clojure file can be linted in 10-40 ms#2019-07-2516:03Crispinomg!#2019-07-2516:03borkdudebut you can also use it on the JVM, as a regular clojure library#2019-07-2516:03CrispinI havent used graal yet, but I did read a blog post about how it can solve the startup time issue#2019-07-2516:04Crispinis it your work, @borkdude#2019-07-2516:04borkdudeclj-kondo is yes#2019-07-2516:06Crispinawesome. I see you have an emacs screenshot on your page. is there an emacs package?#2019-07-2516:06borkdudehttps://github.com/borkdude/flycheck-clj-kondo#2019-07-2516:07Crispinyowza. Im in heaven.#2019-07-2516:08CrispinI think you may have really plugged a hole in the clj ecosystem! Thanks for all your hard work. I will try it!#2019-07-2519:57borkdudeany windows users wanting to help in this issue? https://github.com/borkdude/clj-kondo/issues/372#2019-07-2523:49sogaiuregarding wsl-types of things: iiuc, wsl 2 is on the horizon(?) -- this leaned me away from starting to use the existing wsl. i don't know when it will happen nor what consequences there might be for the remove wsl extension, though.#2019-07-2523:51sogaiu@crispin the flycheck integration has been working pretty well for me -- i only installed it for testing, but now i've become a user 🙂#2019-07-2623:02lread@borkdude and I had an interesting discussion over in #cljdoc about unused destructured keys. It seems they are often used to document the shape of an incoming structure. Because of this, I wonder if it would make sense for clj-kondo to be able to distinguish between unused destructured keys vs the general :unused-binding.#2019-07-2708:02borkdude@lee It's interesting that so far nobody has asked for this. Also it's a relative new feature in joker (a couple of years after people having used it). I really wonder if it's a good idea. I posted a Tweet about it: https://twitter.com/borkdude/status/1155024640231780352 Let's see what others think too.#2019-07-2708:20borkdudeI personally lean towards: if you do it for documentation only, use other means#2019-07-2708:45borkdudehttps://ask.clojure.org/index.php/8214/keys-destructuring-for-documentation-reasons-good-bad-style#2019-07-2709:13sogaiui think the spec alternative may be more attractive once it actually isn't alpha 🙂#2019-07-2714:03lreadMaybe the people who employ unused destructured keys for docs are not using clj-kondo yet? Even if the community unanimously agrees this practice is a bad (or questionable), clj-kondo still might be gracious and offer an option to ignore this specific practice to allow folks to transition to an alternative style at their own pace.#2019-07-2714:04lreadOf course this graciousness is not free, someone has to implement and then maintain it!#2019-07-2715:45borkdude> I never destructure :keys just for documentation; the alternatives you mentioned both sound better. I do often add the :as part without using it, but i'm sure there is no perf penalty in that case. https://ask.clojure.org/index.php/8214/is-keys-destructuring-for-documentation-reasons-good-style?show=8217#a8217#2019-07-2717:02CrispinI've started using clj-kondo with flycheck, and there are places where the destructuring :keys are reported as unused bindings where they are basically documentation. They are more reminders to me, and I may use them on the inner expressions at some point. Some I've removed, but some I just leave. When I leave them it's nice to have the unused ones just underlined for me. So even if it is a form of documentation, when it's editor integrated like this, it's nice to have it highlighted. Just because a linter marks it, doesn't mean I have to alter it. So I like it the way it is. I can see how it might be annoying from the command line, but inside the editor it's kind of nice. Maybe for people using this as a form of documentation/reminder could consider using an editor integration?#2019-07-2717:09borkdudeYou can also switch to :arglists for the functions that need docs#2019-07-2720:49lread@borkdude, current release of clj-kondo is having difficulty with https://github.com/cljdoc/cljdoc/blob/d54cb58b20d2b4cb1e7c714b3637aa8b89956ce0/test/cljdoc/util_test.clj#L28 clj-kondo returns: test/cljdoc/util_test.clj:0:0: error: can't parse test/cljdoc/util_test.clj, Invalid symbol: org/clojure/math.numeric-tower. I can easily work around this for my purposes but I thought you’d like to know. Happy to raise a git issue if one is merited.#2019-07-2721:11borkdude@lee issue would be fine#2019-07-2721:11lreadwill#2019-07-2721:11lreaddo#2019-07-2721:13borkdudeyou'll probably also run into this one with rewrite-cljc, as this is a tools.reader issue#2019-07-2721:13borkdudeI have hacked around this for some other issue, I think it was a similar one for keywords#2019-07-2721:14borkdudehttps://github.com/borkdude/clj-kondo/blob/master/parser/clj_kondo/impl/rewrite_clj/parser/keyword.clj#L14#2019-07-2721:44lreadthanks, I shall make a note of that!#2019-07-2721:44lreadhere’s the git issue: https://github.com/borkdude/clj-kondo/issues/378#2019-07-2721:52borkdudethank you!#2019-07-2721:52borkdude@lee I'm currently playing with this: https://www.dropbox.com/s/ewrpwwrj53aktt0/Screenshot%202019-07-27%2023.52.25.png?dl=0#2019-07-2722:37lreadwooo! :analysis = import-vars smart?#2019-07-2723:12sogaiuis there a straight-forward way to figure out the full path of the file that corresponds to a particular namespace?#2019-07-2723:23lreadhi @sogaiu! with regards to analysis?#2019-07-2800:41sogaiu@lee yes, i think. the cache files for clj-kondo contain def info too w/ ns info, but no file path. when the cache is created one can pass in a classpath, but this doesn't appear to get saved anywhere.#2019-07-2811:16lreadah, I thought you might have been talking about clojure analyzer, which you were not. simple_smile Since you have the classpath I suppose you could search it as a post processing step to find your files (some of which will be in jars)... or you could ask @U04V15CAJ to add more info to clj-kondo output.#2019-07-2811:17borkdudeI'm building this feature: https://twitter.com/borkdude/status/1155235517258260481 so people don't have to rely on implementation details of the cache#2019-07-2811:17borkdudeit's in a branch called dump-analysis, feel free to give it a go#2019-07-2811:17borkdudeit's work in progress, so things might still change#2019-07-2811:22sogaiu@lee actually, i don't have the classpath -- i was hoping to get it (or file paths for namespaces) from clj-kondo somehow 🙂 the upcoming(?) clj-kondo analysis feature definitely looks like it could be quite relevant.#2019-07-2811:22sogaiuthanks for the branch tip.#2019-07-2811:23borkdudethere is also this issue: https://github.com/borkdude/clj-kondo/issues/373#2019-07-2811:38sogaiuafter running a freshly built version, i see the filepaths among the analysis output now -- looks promising 🙂#2019-07-2806:45sogaiugiven:
(ns wo)

(with-open [out ( "/tmp/remove.this.txt")]
  (.write out 65))
as wo.clj, clj-kondo --lint wo.clj works fine (no info messages, just a summary output). as wo.cljc, clj-kondo --lint wo.cljc gives:
wo.cljc:3:2: info: unresolved symbol with-open
wo.cljc:3:13: info: unresolved symbol out
linting took 48ms, errors: 0, warnings: 0
this is with 18d97a6c3ca7d5d9eba351aa4291fc828bd2b215 -- why is the behavior different?
#2019-07-2806:50borkdudeBecause with-open doesn’t mean anything in CLJS. You have to put a conditional around it#2019-07-2806:51borkdudeThe export is not aware of import-vars yet#2019-07-2807:11sogaiuah, that makes sense. thanks for the explanation!#2019-07-2810:37Jeevaraj MVI’m not able to get installation process for Joker #2019-07-2810:37Jeevaraj MVCan anyone pls let me know #2019-07-2811:16borkdude@jeevarajmvsvg do you mean clj-kondo together with joker?#2019-07-2818:41borkdudehttps://github.com/borkdude/clj-kondo/tree/dump-analysis/tools#2019-07-2819:42lreadnice#2019-07-2907:28Jeevaraj MV@borkdude no only joker #2019-07-2907:28Jeevaraj MVIt’s working fine in Ubuntu machine #2019-07-2907:29borkdudeif it's about joker, you might want to ask in #joker#2019-07-2907:29Jeevaraj MVYes #2019-07-2907:29Jeevaraj MVBut I need more info on windows machine #2019-07-2916:07lreadFYI https://github.com/cljdoc/cljdoc/pull/338#2019-07-2917:57Jeevaraj MVThank you #2019-07-2920:18lreadmy pleasure!#2019-07-2916:11borkdudeawesome work. some remarks:
:not-empty? false
should be
:not-empty? {:level :off}
#2019-07-2916:13borkdudeit seems you are linting in two steps, one to populate the cache and one for results you want to see. this is unnecessary, you can use the config to show only results of files you're interested in#2019-07-2916:38kszaboHow does one do that? I didn’t find anything relevant under :output#2019-07-2916:38kszabohttps://github.com/borkdude/clj-kondo/blob/55c52ad8d753d17e9d5216d385385014938bb7a1/src/clj_kondo/impl/config.clj#L68#2019-07-2916:39kszabo:include-files only applies to the current dir, not for dependencies#2019-07-2916:39borkdudecan you make a repro of this? it might be a bug#2019-07-2916:40borkdudeclj-kondo has no notion of "current dir", it just lints whatever you give it, but it does handle relative paths#2019-07-2916:44kszaboah right#2019-07-2916:44kszaboIn our Jenkins build we run clj-kondo twice#2019-07-2916:44kszabofor the cache building part we ignore errors, so dependency source issues don’t fail the build#2019-07-2916:45kszabothen we run it again with our own lintPaths#2019-07-2916:45borkdudeyou shouldn't have to, feel free to post an issue if it doesn't work like expected#2019-07-2916:48kszaboah, I see now. We should just set :include-files#2019-07-2916:48kszabothe comment threw me off#2019-07-2916:48kszabothx!#2019-07-2917:10lread@U08E8UGF7, I just tried it and it works over here. If you only want your sources included, one tip is to prefix your dirs with ./ for example:
:output {:include-files ["./src" "./test" "./modules"]}
#2019-07-2917:18borkdudeyou can use ^ and $, these are regexes#2019-07-2917:22lreadhmmm… ya something is off with my example. I’ll try regex.#2019-07-2917:24lreadthanks @borkdude, the following gave me expected results:#2019-07-2917:24lread:output {:include-files [“^src” “^test” “^modules”]}#2019-07-2917:36lreadoh right… I took a shortcut, cljdocs contains a few tiny sub-projects under modules. So I build my cache with the main deps.edn and use it against the sub-projects. So… I might stick with my 2 step shenanigans for now.#2019-07-2917:37lreadworthy of a comment in my shell script anyway.#2019-07-2917:39borkdudebut why not lint all of that in one go?#2019-07-2917:42borkdudeI mean, you can just do $(clojure -Spath) src test modules?#2019-07-2917:45lreadoh gee. yeah why not? I think I might have been fixated on building that cache separately as prep step. thanks.#2019-07-2917:46borkdudesrc is probably already in the path the clojur provides, so just add test and modules#2019-07-2917:46borkdudethose modules also already seem to be on the path: https://github.com/cljdoc/cljdoc/blob/master/deps.edn#L58#2019-07-2917:47borkdudeso you can just do $(clojure -C:test -Spath) maybe#2019-07-2917:49lreadhmmm… good points… oh… deps.edn does not include all modules… you’ve given me great guidance… thanks for your patience!#2019-07-2917:56borkdudeactually you need both -R and -C test, R to get the test deps and C to include the test dir itself. I don't know if there is anything in tools.deps that combines those#2019-07-2918:15lreadok must go study -R and -C, thanks @borkdude!#2019-07-2918:15borkdudesee #tools-deps#2019-07-2918:25lreadtx#2019-07-2918:42borkdudeone small thing: why are you creating a cache? are you re-using it somewhere later?#2019-07-2918:44borkdudenot that it matters, in CI everything is mostly a one off thing#2019-07-3012:12lreadsorry, missed this one! good question. the script is meant for developers and ci. ci won’t make use of the cache.#2019-07-3012:34borkdudecheck#2019-07-2916:20borkdude^ @lee#2019-07-2916:33lreadthanks for the tips!#2019-07-2916:35borkdudethe reason for not empty: just look in the docstring of empty?#2019-07-2916:45lreadyeah I saw that… and thought it was a bit preachy… I probably don’t understand the rationale… if that is the idiom clojure authors are recommending I should follow suit.#2019-07-2916:46borkdudethe reason is that empty? calls seq again, so (not (empty? ...)) is really (not (not (seq ...)), but then you could just write (seq ...)#2019-07-2916:49lreadthat’s just an implementation detail though, no? The (not (empty? x)) reads pretty clearly to me. That said, I’m going to go with the flow and use (seq x). I’m getting more used to it as we chat about it. simple_smile#2019-07-2916:37borkdudeas for destructuring: feel free to post an issue in clj-kondo. it seems a thing people want to be doing in function arguments without getting warnings. so maybe something like {:unused-bindings {:arguments false}} but that would turn off the warning for all function arguments#2019-07-2916:51lreadI will raise a git issue and reference your question to the community on the topic.#2019-07-2922:07borkdude@lee https://github.com/borkdude/clj-kondo/issues/382, I think that's how I want to support it#2019-07-2922:09lreadthere is a nuance I noticed: people sometimes leave in an unused :as x to describe the overall type.#2019-07-2922:10lreadI think your config is good, but might not be extensible should you want to, in the future, exclude other types of things?#2019-07-2922:10borkdudegood point#2019-07-2922:12borkdudeit's extensible by just adding a new key for that scenario, but right now I haven't come across many other situations where I would want to suppress these messages. maybe the :as is a good one, but we can just fit that under this option I guess#2019-07-2922:13borkdudejoker has some options for this, but they are a bit too coarse: like, turn off everything always in function arguments#2019-07-2922:14lreadI don’t know if you need to have separate options for excluding keys and :as … do you?#2019-07-2922:15borkdudeyou can always do :as _foo#2019-07-2922:15borkdudeI do that a lot actually, :as _ctx#2019-07-2922:16lreadthat would work for me.#2019-07-2922:17borkdude
There is a new rule :unused-keys (defaults to true) which applies to :keys, :strs, and :syms bindings.
This is what joker calls it
#2019-07-2922:17borkdudebut I would like to enable this only within function arguments#2019-07-2922:17lreadyes indeed#2019-07-2922:18lreadjust remembered another interesting case: defmulti: example: https://github.com/cljdoc/cljdoc/blob/d77e5918ddd356a97b95281153e0c8a53866e1e9/src/cljdoc/render.clj#L20#2019-07-2922:19borkdudemaybe just:
{:linters {:unused-binding {:destructured-fn-args false}}} ;; defaults to true
#2019-07-2922:21borkdude@lee I would do that like this:
(defmulti render (fn [page-type _route-params _cache-bundle] page-type))

(defmethod render :default
  [page-type _ _]
  (format "%s not implemented, sorry" page-type))
#2019-07-2922:21lreadI’m just looking are your default clj-kondo config. You do use the the key :exclude for other things.#2019-07-2922:21borkdudesince it's very clear that the latter two args aren't used to dispatch#2019-07-2922:24lreadya when I clj-kondofied, I prefixed with underscores. Makes sense to me, I think others would agree?#2019-07-2922:28lreadah I see from chat above, you agree#2019-07-2922:23borkdudeI'm usually using the key :exclude for things like vars and namespaces, but :exclude [:destructured-fn-args] would be a bit weird#2019-07-2922:23lreadBut in this case you might consider :exclude-checks [:destructured-fn-args]#2019-07-2922:23lreadright, agreed, if used would have to qualify#2019-07-2922:25borkdudeyou can also disable the entire linter in just one namespace, using a namespace local config#2019-07-2922:25borkdudeit doesn't work for every linter yet, but if needed, I could make it work#2019-07-2922:26lreadwas not aware of that, cool.#2019-07-2922:26borkdudeI didn't document it until the previous release, but it's been there for a while, mostly for my own debugging#2019-07-2922:27borkdudeafk now, zzz#2019-07-2922:28lreadlater! have a good zzz#2019-07-2922:33lreadya know what? I don’t really see anything wrong with your:
{:linters {:unused-binding {:destructured-fn-args false}}} ;; defaults to true
You might consider something a bit more descriptive:
{:linters {:unused-binding {:exclude-destructured-fn-args false}}} ;; defaults to true
#2019-07-2922:35lreadwhile… you sleep… also: this is just for destructured key fn args though right? So maybe:
{:linters {:unused-binding {:exclude-destructured-key-fn-args false}}}
#2019-07-3007:32borkdudewhy would you only want to exclude key fn args? e.g. (defn -main [& [a b c & _ :as args]]) might also fall under this behavior?#2019-07-3007:33borkdude
user=> (defn main [& [a b c & _ :as args]])
#'user/main
user=> (doc main)
-------------------------
user/main
([& [a b c & _ :as args]])
same thing if you ask me, you destructure for the doc benefits
#2019-07-3007:36borkdudeso maybe this setting should be named something like :exclude-destructured-public-args to emphasize it will only happen in public functions created with defn and defmacro?#2019-07-3012:37lreadI’m probably not using the correct terms. If I RTFM simple_smile https://clojure.org/guides/destructuring , I am suggesting that this option won’t ignore unused sequential destructuring, for example:
(defn print-coordinates-3 [[x y z]]
  (println "x:" x ", y:" y "))
would still issue a warning about unused z.
#2019-07-3013:02borkdudeI think so yes#2019-07-3013:24lreadso that’s why I introduced the word keys but it might not be the right word. :exclude-associative-destructured might be closer to correct?#2019-07-3013:25borkdudea vector is also associative#2019-07-3013:25borkdudeso keys is better if you want to exclude vectors#2019-07-3013:39lreadright you are, of course. https://clojure.org/guides/destructuring#_associative_destructuring#2019-07-3007:47borkdudeor maybe you are destructuring only for yourself, not for a public consumer, so :exclude-destructured-fn-args seems best to me#2019-07-3009:58borkdudeanyone wants to play with this data https://github.com/borkdude/clj-kondo/tree/dump-analysis/analysis#data before I release it tomorrow?#2019-07-3010:30sogaiu@borkdude it looks interesting! unfortunately, i don't have the set up to try it before tomorrow -- unless just building the dump-analysis branch is enough? is it correct that the filenames will be full paths or is that based on what is passed in originally?#2019-07-3010:31borkdudeit's based on what you pass in originally, but it's possible to make that configurable, if you need that. I could also include the jar file names if you want#2019-07-3010:33borkdudethat could also be useful for the linter itself. {:output {:filenames :absolute}} or something#2019-07-3010:34sogaiuiiuc, because from other tooling it's not possible to know what the classpath was when the analysis was done, i'm not sure i can reliably determine the exact files in question. i hope it can be worked out appropriately 🙂#2019-07-3010:34borkdudeit can, because it reads them#2019-07-3010:36sogaiusounds good 🙂#2019-07-3010:36borkdudeI think this can be implemented as a seperate issue: https://github.com/borkdude/clj-kondo/issues/383#2019-07-3010:37sogaiupossibly on a related note, would it be possible / useful to be able to recover the classpath that was used at the time of analysis?#2019-07-3010:37borkdudeI could just return the :lint option that was used, that would be the most flexible, so what you pass in, you get out#2019-07-3010:38borkdudeI don't see yet how that would be useful, since you know what you passed in already#2019-07-3010:40borkdudenote that when you call clj-kondo with an absolute path, you will already get an absolute path back#2019-07-3010:40sogaiui was thinking whether tooling might make use of a user's previous invocation of clj-kondo -- so the tooling wouldn't necessarily know what was used for the classpath#2019-07-3010:41borkdudewouldn't the tooling itself invoke clj-kondo?#2019-07-3010:41borkdudeif absolute paths are included in the output, return the lint arguments doesn't add much value I think for tooling#2019-07-3010:42borkdudesince the tooling already knows where to find those files?#2019-07-3010:42sogaiuit might, but the user is the one who knows what classpath they want, and if the tool could just read that info from somewhere (e.g. if clj-kondo stored it in its cache), then the tool doesn't have to bother the user about it#2019-07-3010:42sogaiui was actually thinking to use clj-kondo's api to make an extension / plugin -- not ask the user to install clj-kondo#2019-07-3010:43borkdudein the JVM right?#2019-07-3010:43sogaiuactually, i was going to build a native-image binary#2019-07-3010:43borkdudebut then you will need to have clj-kondo installed, I don't get it#2019-07-3010:43borkdudeare would you bundle clj-kondo with your binary#2019-07-3010:43sogaiuno, it is not necessary, because clj-kondo provides an api#2019-07-3010:44sogaiuclj-kondo can be used as a dependency#2019-07-3010:44borkduderight, that's true#2019-07-3010:44sogaiui think i tried this already a bit back#2019-07-3010:44borkdudein which editor were you going to use this?#2019-07-3010:45sogaiuthis is part of the experimental project to make editor independent tooling -- so far the editors i have been experimenting with are emacs, atom, and vscode#2019-07-3010:45sogaiuthey all use the same native-image binaries#2019-07-3010:45borkdudevery cool#2019-07-3010:45sogaiuand provide thin "glue" to talk to it#2019-07-3010:46borkdudelet's just start with the things you need concretely, without speculating too much. I'll add the full file paths option for starters#2019-07-3010:46sogaiuthanks! that'd be great -- i am hoping to implement "find definitions" for starters
#2019-07-3010:49borkdudeso the full file path for e.g. clojure.core/defn would be in my case /Users/borkdude/.m2/repo/../../../clojure-1.10.1:jar:clojure/core.clj but if you're linting only one file without any dependencies like clojure itself, defn is resolved from a built-in cache which has no filenames#2019-07-3010:51borkdudeso it all depends on what your editor tooling is linting. you can ask the user to index your entire classpath whenever one of the dependencies change#2019-07-3010:51borkdudeand then you can save that analysis information somewhere#2019-07-3010:54borkdudebut I guess you don't have to wait for this, just invoke your binary with a full path#2019-07-3010:59sogaiuyes#2019-07-3012:55lreadI am thinking about eventual use of clj-kondo from cljdoc. Cljdoc takes the convention (and code) from codox to exclude namespaces/fns/vars marked with :no-doc metadata. Would this be possible with clj-kondo?#2019-07-3013:00borkdude@lee I can include that metadata in the analysis data#2019-07-3013:02lreadthat would do the trick!#2019-07-3013:04borkdudeI think including :deprecated is also good#2019-07-3013:05borkdudemaybe docstring as well?#2019-07-3013:05borkdudeI don't currently save that anywhere#2019-07-3013:05borkdudeI do have a linter for misplaced docstrings in defn#2019-07-3013:08borkdudeadded it here: https://github.com/borkdude/clj-kondo/issues/373#issuecomment-515740595#2019-07-3013:33lreadyeah docstring too. This is what codox currently harvests: https://github.com/cljdoc/codox/blob/b29b16ae686e3400689bbdc93df57200b709443d/codox/src/codox/reader/clojure.clj#L131#2019-07-3013:35borkdudethank you, I'll add that link to the issue#2019-07-3013:37borkdudeI'm not sure if I'll get everything in before tomorrow's release, but you won't be using it anyway before import-vars is supported#2019-07-3013:37borkdudeand I expected the latter to be a bit more involved, but not undo-able#2019-07-3013:38borkdudeI want to introduce the concept of a redirect, so when you do (def a 1) (def b #'a) which I think is what import-vars is doing, then var b is redirected to var a, so when you call b, you also call a#2019-07-3013:38borkdudeand then I'll have to analyze import-vars and make use of this new redirect concept#2019-07-3021:56robertfwIs it possible to disable all :unused-namespace warnings for a given namespace? I'd like to disable it for my dev namespace (my usual home at the repl) as it brings in a variety of utility functions to make them available while developing#2019-07-3022:12borkdude@robertfrederickwarner you can using a namespace local config#2019-07-3022:12borkdudebut you can also solve that with declare#2019-07-3022:13borkdudeor you can avoid using use and refer :all (although clj-kondo is able to resolve them when you use a cache)#2019-07-3022:13borkdudesee: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#2019-07-3022:32robertfwThanks. I'll probably go with the namespace local config - seems the most minimal#2019-07-3022:33robertfwAbsolutely love the tool, it's helped clean up a bunch of code in the past two weeks or so I've been using it#2019-07-3022:36borkdudegood to hear 🙂#2019-07-3022:41robertfwI've put in the local config and toggle syntax checking on and off (my usual routine after modifying my kondo config), but it doesn't appear to be working#2019-07-3022:41borkdudethe namespace local config doesn't work for all linters yet#2019-07-3022:42borkdudeI thought you were only speaking about unresolved symbols#2019-07-3022:42borkdudebut when you remove the alias (since you don't need it) clj-kondo won't report that as unused#2019-07-3022:42robertfwah. i guess because this is linting a namespace that would make sense#2019-07-3022:42borkdudeso only [clojure.core.async]#2019-07-3022:43borkdudeyou can also just exclude your dev file from the linting output if you want#2019-07-3022:43robertfwnah, i'll just leave it for now - would like to still have linting throughout the rest of the file. not a big deal.. just trying to clean things up as much as possible#2019-07-3118:24robertfwSo up until now I've been using clj-kondo via spacemacs integration, and that's been working great. I just tried running from the command line, so that I could get a full-project check, and I'm running into issues running on the VM that my project lives on. It runs fine locally (i.e., directly on my mac host), but when I run in the vm I get lots of "file does not exist" warnings, and it doesn't seem to see my .clj-kondo directory with config/cache. Are there any known quirks of running in a VM, or have I just run into some peculiarity of our setup?#2019-07-3118:26borkdudeclj-kondo is tested with linux and Mac in CI, so it's likely an issue with your setup#2019-07-3118:26borkdudemaybe a permission issue#2019-07-3118:26borkdudealthough "not exists" usually means it really doesn't exist#2019-07-3118:26borkdudewhat OS is your VM running, linux?#2019-07-3118:28borkdude^ @robertfrederickwarner#2019-07-3118:28robertfwYup, ubuntu 18.04.02#2019-07-3118:30robertfwThanks, I just wanted to check if there was anything known before I started my dig. I had taken a look through the open issues but hadn't spotted anything seemingly related.#2019-07-3118:32borkdudeI'm just working on a feature that does this: $ clj -A:clj-kondo --lint foo foo:0:0: error: file does not exist linting took 11ms, errors: 1, warnings: 0 $ clj -A:clj-kondo --lint foo --config '{:output {:canonical-paths true}}' /Users/borkdude/Dropbox/dev/clojure/clj-kondo/foo:0:0: error: file does not exist linting took 9ms, errors: 1, warnings: 0#2019-07-3118:33borkdudemaybe that would be helpful to find your error?#2019-07-3118:36robertfwCouldn't hurt!#2019-07-3118:37borkdudeok, linux binary coming up#2019-07-3118:37robertfwexcellent, thanks 🙂#2019-07-3118:38borkdudeI was just about to push this release out, but now I've got a tester, how wonderful#2019-07-3118:39borkdude@robertfrederickwarner here you go: https://5148-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.07.25-alpha-SNAPSHOT-linux-amd64.zip#2019-07-3118:41robertfwusing that directly, everything works normally#2019-07-3118:42robertfwi'll see if i can swap that into the spot that the existing binary is and run it that way#2019-07-3118:44robertfwI'm wondering if it's related to this command actually: sudo snap connect clj-kondo:home - we don't have our code in the home directory (it lives in /vagrant, which is mounted from the host)#2019-07-3118:45robertfwThis is my first foray into using snap so I'm not familiar with how it connects everything up#2019-07-3118:45borkdudeyes, that's related. snap binaries don't have access to anything other than the home dir#2019-07-3118:45borkdudesecurity#2019-07-3118:45borkdudethe alternative is to use brew for linux#2019-07-3118:46borkdudenothing I can change there#2019-07-3118:46borkdudeor maybe you can install it with classic or dev settings and then it would work, not sure#2019-07-3118:48robertfwI'll have a browse through the snap docs and see what I can find#2019-07-3118:49borkdudeok#2019-07-3118:49borkdudeI'll push out the current release then#2019-07-3119:19borkdudeclj-kondo v2019.07.31-alpha This version includes the ability to output analysis data which allows building custom linters and tools. Happy hacking! https://github.com/borkdude/clj-kondo/releases/tag/v2019.07.31-alpha#2019-07-3119:19borkdude(@sogaiu: it also includes printing full paths)#2019-07-3121:21sogaiu@borkdude sounds great! hope to try it soon :)#2019-07-3121:38dharriganarch updated.#2019-07-3121:46borkdudethanks, I hope you're not getting tired of updating#2019-07-3122:08lreadwith each new release my code gets cleaner and my scripts & config get smaller, so happy camper here!#2019-07-3122:39robertfwIs there a delay for new releases to hit snapcraft? I tried refreshing my snap to get the latest but am not seeing the new version. The snapcraft page is still showing the July 24th release https://snapcraft.io/clj-kondo#2019-07-3122:40borkdudeoh, I have to release it manually after a push I think#2019-07-3122:40borkdudecan you try again?#2019-07-3122:41robertfwstill seeing the earlier version#2019-07-3122:43borkdudeshould be good now#2019-07-3122:43robertfwyup! seeing the new version now#2019-07-3122:43robertfwthanks 🙂#2019-08-0107:20josehi, I was thinking about clj-kondo and editor integration, and I'd like to know if there is any performance difference between the graal version and the jvm version (running is a repl)#2019-08-0107:21joseFor example, I think that if you have a project with multiple fies, the graal version needs to scan all the files every time you invoke it. While if clj-kondo is running in a repl and called from your editor, in theory it could do some caching, since the editor can tell what files changed.#2019-08-0107:27joseI saw in the project readme that is possible to create a cache, but I guess (correct me if I'm wrong) that anyways you need to check the timestamps for all the files in your project#2019-08-0107:28borkdude@jlle when using clj-kondo with an editor, you first create a cache. after that, your editor incrementally lints files and this also updates the cache#2019-08-0107:29borkdudeso when you change a function in namespace A and go to namespace B where that function is called, you will immediately see an arity error for example#2019-08-0107:30joseok, so it should not matter if I run the graal or the jvm version#2019-08-0107:30borkdudeI prefer the GraalVM version for editors, so I can already see things when I don't even have a REPL#2019-08-0107:32josethanks for clarifying it, in that case I also prefer the graalvm version 🙂#2019-08-0119:31jvtriguerosI've been doing Clojure for a while and I constantly write (not (empty? coll)) instead of (seq coll) (as suggested by clj-kondo), does anyone have a link for the rationale? I'd like to write more idiomatic Clojure, but also want to understand why 🙂#2019-08-0119:44sashtonhttps://github.com/clojure/clojure/blob/clojure-1.9.0/src/clj/clojure/core.clj#L6127-L6128#2019-08-0119:44jvtriguerosThank you!#2019-08-0119:45sashtonI guess the thinking is (not (empty? coll)) becomes (not (not (seq coll))). So just use (seq coll) instead.#2019-08-0211:18sogaiui'm looking at analysis output and seeing that there appear to be duplicates among the maps within the vector value of the :namespace-definitions key. there appear to be pairs of maps that are the same. is this expected behavior? (this is with 300d8fdf48324d662ad28b59d8a071de34d07a82)#2019-08-0211:20sogaiumay be it's because the files analyzed were .cljc fies, for each pair, one is for clj and the other is for cljs?#2019-08-0215:07borkdudeFor cljc that is expected, the :lang key explains the difference#2019-08-0215:08borkdudeSome thing may or may not be defined in one language but may be in another#2019-08-0220:56lilactownI'm trying to follow the instructions for https://github.com/borkdude/clj-kondo/blob/master/analysis/README.md#example-tools the namespace graph#2019-08-0220:56lilactownI'm getting an error
Execution error (IOException) at java.lang.ProcessImpl/forkAndExec (ProcessImpl.java:-2).
error=2, No such file or directory
#2019-08-0220:58lilactownah I bet I need graphviz installed#2019-08-0220:59borkdude@lilactown Correct, if you scroll down to the namespace graph example: https://github.com/borkdude/clj-kondo/blob/master/analysis/README.md#namespace-graph#2019-08-0221:02borkdudeMaybe I should take another example in that part where I describe how to use it as an alias, that doesn't need any other tools#2019-08-0221:05lilactownI ran it on our work project and the png won't load in Preview 😂#2019-08-0221:05lilactownit's 24mb#2019-08-0221:05borkdudehaha, I also got a very large one with our project. maybe adding a filter using a regex is nice#2019-08-0221:06borkdudeso you can only see your own namespaces#2019-08-0221:06lilactownyeah, at work we want to know e.g. between two ns, what the path looks like (if any)#2019-08-0221:07borkdudeyou can take the code and change it to your likings, since it's just an example#2019-08-0221:08borkdudehttps://github.com/borkdude/clj-kondo/blob/master/analysis/src/clj_kondo/tools/namespace_graph.clj#2019-08-0221:12lilactowngreat thanks!#2019-08-0302:44sogaiu@borkdude the files in question were .cljc, but fwiw, there is no lang key within each map. a typical example is:
{:col 1,
 :filename "src/augistints/core.cljc",
 :name augistints.core,
 :row 1}
just reporting here for completeness, not trying to make a point 🙂
#2019-08-0306:19borkdudedo you have the source code that goes along with it? then I can take a look#2019-08-0306:30sogaiuhere is a repository url: https://github.com/sogaiu/augistints i ran the following command in the project directory: clj-kondo --lint src --config '{:output {:analysis true :format :edn}}' > analysis.edn then examined the content of analysis.edn#2019-08-0306:43borkdudeyou're right, I haven't added those :lang keys over there yet.#2019-08-0306:44borkdudeI'll add them for the next release#2019-08-0306:59sogaiusounds good! thanks 🙂#2019-08-0422:02sogaiuis it doable to have script/compile check PATH for native-image? in at least one of my setups, i don't have GRAALVM_HOME set, but i have native-image on my PATH#2019-08-0422:05borkdudePR welcome#2019-08-0422:05sogaiuok, will take a look#2019-08-0509:14shemI installed clj-kondo via snap on a kubuntu 19.04 machine and am seeing strange behaviour:#2019-08-0509:14shem#2019-08-0509:15borkdudeclj-kondo with snap cannot read files outside of your home directory#2019-08-0509:15borkdudethis is one of the security behaviors of snap#2019-08-0509:15shemright. is there any way to grant it more permissions?#2019-08-0509:16borkdudeI think there is, but you have to go through their vetting procedures. installing via brew for linux might be easier for you then#2019-08-0509:16borkdudeor .aur if you're on arch#2019-08-0509:16shemok, thanks for the info.#2019-08-0509:17borkdudeyou can also use the install script which just downloads the binary from github and places it in a directory of choice (/usr/local/bin by default)#2019-08-0509:17shemi'll try that#2019-08-0516:20bedershi there, is there already a linting rule for something like this: (= "foobar") ?#2019-08-0516:21bedersi.e. only using one arg with = which might be worth a warning#2019-08-0516:24borkdude@beders https://github.com/borkdude/clj-kondo/issues/260#2019-08-0516:24bedersthank you! should have checked there first 😉#2019-08-0516:25borkdudenp#2019-08-0604:58viestihum, was just mocking a function with with-redefs to return a canned response and wondered how to make the squiggly line under unused argument go away and happened to put a underscore in front and it did the trick, like:
(with-redefs [clojure.core/identity (fn [_argument] 42)])
Felt like a useful thing, maybe this is a pattern even that didn't know 🙂
#2019-08-0606:37pithylessThere is a style-guide rule to use underscores for unused bindings: https://guide.clojure.style/#underscore-for-unused-bindings There is also an extension of that rule, such that you can use an underscore followed by a name to give a binding a name, but to specify it will not be used (so, for documentation purposes only). IIRC, both clj-kondo and joker implement this extension.#2019-08-0606:38pithylessIt seems intuitive to me, but honestly I just now realize this is a convention I was already familiar with from the ML-based languages (Haskell, OCaml).#2019-08-0607:01pithyless^ @borkdude WDYT of linting the opposite? Reporting that an "underscored" binding was used. This to me sounds similar to using def inside a defn => something you may want to do during development, but not something you want to commit.#2019-08-0607:01pithyless
❯ echo '(defn foo [_x] _x)' | clj-kondo --lint -
#2019-08-0607:24borkdude@pithyless I've thought about that, but it I'm not 100% sure if that's a good idea. in some cases it might be desirable to call your binding _foo_ while also be able to use it without a warning?#2019-08-0607:25borkdude_ is a way to disable the linter. I think the mode "you're on your own now" makes sense#2019-08-0607:29pithylessFair enough; for me the _ is a useful pattern to document unused arity arguments or side-effecting let bindings, but I have not personally thought of it as "you're on your own". ¯\_(ツ)_/¯#2019-08-0607:30borkdudeIn practice, when using variables with an underscore when it's not a binding will probably make you change it anyway, in my experience.#2019-08-0607:34pithyless^ I agree with this sentiment, which was actually my reason for raising the idea. If you think of a linter as an automated PR check to make sure that reviewer time is not spent on pointing out things that could have been automated, then I would argue that any code that is referencing _foo should get a warning. This could be a either because something was missed during the commit phase or someone is simply unaware of the convention that will trip up other readers.#2019-08-0607:36pithylessBut I'm not prepared to die on the hill for this; we can just as easily drop it ;]#2019-08-0607:36pithylessI wonder how prevalant it is to use _foo_ or _foo intentionally in real codebases... :thinking_face:#2019-08-0607:48sogaiuthere isn't a crossclj replacement to make queries of this sort, right? perhaps it will be something the cljdocs folks will take on eventually...#2019-08-0607:51borkdude@sogaiu did crossclj ever have information about local bindings?#2019-08-0607:52borkdude@pithyless it's an interesting idea, I'm just not sure if it will lead to unwanted warnings. it could be an optional linter that's not on by default#2019-08-0607:53sogaiui do not know if crossclj had info on local bindings.#2019-08-0607:53borkdudeclj-kondo could emit it in the analysis info#2019-08-0607:54borkdudethat will lead to loads of data, but it could be optionally on#2019-08-0607:54borkdudehttps://github.com/borkdude/clj-kondo/tree/master/analysis#2019-08-0608:23yuhanI've noticed that flycheck-clj-kondo chokes up on certain syntax errors like a single colon : or a incomplete namespaced symbol foo/, and just outputs a single error on the first line of the file with a message referencing the actual error location#2019-08-0608:24yuhanIs this a bug with the linter output format or some sort of reader limitation?#2019-08-0608:26yuhaneg. other read-time syntax errors like {a} produce a lint error directly at the point without the rest of the file being affected#2019-08-0608:26borkdudeI think it's a reader limitation, since tools.reader chokes on it#2019-08-0608:26borkdudeit could potentially be improved#2019-08-0608:38yuhanhmm yeah, it's friendlier if the line/col info from the reader-error could be propagated to the linter output#2019-08-0608:40yuhanI assume Flycheck would then pick it up and display the squiggly line at the correct place#2019-08-0609:03borkdudefeel free to post an issue with this#2019-08-0612:31manuel@borkdude chiming in here to say THANK YOU for clj-kondo and flycheck-clj-condo. Simple to install and use. Great stuff indeed. 🙂#2019-08-0620:56mynomotoOn the latest release clj-kondo is not using the created cache. I have a file with warnings when I run clj-kondo --lint "$(clj -A:dev -Spath)" --cache but not when I run clj-kondo --lang clj --cache the-file-with-warnings Am I doing something wrong?#2019-08-0621:00borkdudethe (optional) argument to --cache is a directory. you should pass the file to lint to --lint#2019-08-0621:00borkdudeso: clj-kondo --lang clj --cache --lint the-file#2019-08-0621:03borkdude@mynomoto ^#2019-08-0621:03borkdudethank you for your issue on schema defmethod, I'll take a look later this week#2019-08-0621:36mynomoto@borkdude thanks, I was sure that I tried what you suggested earlier but it sure worked now.#2019-08-0621:36mynomotoIs lang mandatory when using the cache?#2019-08-0621:40borkdudelang is derived from the file extension. the cmd line option is only used when you lint from stdin because then this information isn't there#2019-08-0621:41mynomotoOk, good to know, thanks. I need to do a pr on Ale for it to use the cache on vim.#2019-08-0621:42borkdudeyes, that's a good idea#2019-08-0621:44borkdudemaybe I can change the default for the cache option, because there's also an issue at @marc-omorain’s clojure-lint for this, which isn't fixed yet#2019-08-0621:44borkdudeso: always use the cache if you can find a .clj-kondo directory... not sure if that's a good idea#2019-08-0621:48mynomotoI was thinking about it and what worries me is stale caches.#2019-08-0621:48mynomotoI mean for this be the default.#2019-08-0621:50mynomotoI think you posted a command to do the whole cache but output only project files. Was that a grep on the results or it is a clj-kondo option? Or I'm just imagining things?#2019-08-0621:50borkdudeit's an option in the config yes#2019-08-0621:51borkdudehttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md#include-and-exclude-files-from-the-output#2019-08-0621:54borkdudemaybe these editor plugins should allow you to pass in extra arguments yourself#2019-08-0622:09mynomotoThis is great, thanks!#2019-08-0710:49borkdudefun example using jet, a CLI to query EDN and convert to JSON: https://github.com/borkdude/jet/blob/master/doc/query.md#find-unused-private-vars-using-clj-kondo-analysis-output#2019-08-0815:20gordonHowdy! First things first, thank you for the work on clj-kondo, it's found a few genuine bugs for us, really useful bit of software. I think I've found a false-positive with the :missing-test-assertion linter in 2019.07.31-alpha
(ns false-positive.reproduction-test
  (:require [clojure.test :refer (are deftest)]))

(deftest missing-test-assertion-false-positive
  (are [v expected?] (expected? (contains? #{:bar :baz} v))
       :foo false?
       :bar true?
       :baz true?))
Results in the warning /Users/gordon/Development/foo/test/false_positive/reproduction_test.clj::: warning: missing test assertion I haven't reproduced this in a clean environment outside my employer's main repo, but we don't have any :missing-test-assertion config in .clj-kondo/config.edn so I hope it's generally valid. If not I'll happily put the legwork in to get a properly standalone test case.
#2019-08-0815:22gordonThe line and column numbers are missing from the warning as well, I'm assuming that's down to the expansion of are.#2019-08-0815:24borkdudethis is definitely a bug#2019-08-0815:26borkdude@gordonsyme_clojurians the code you posted is enough of a reproduction#2019-08-0815:26borkdudefeel free to post it in an issue and this will be fixed in the next release#2019-08-0815:26gordonWill do, thanks#2019-08-0912:25tianshuHi, I found this
(let [x 1
      {:keys [y] :or {y x}} {:z 2}]
  y)
x will be warned as a unused variable here
#2019-08-0912:37lispyclouds@borkdude https://circleci.com/build-environments/windows/#2019-08-0912:38lispycloudslooks like we're on! 😄#2019-08-0912:38borkdudeaw yeah!#2019-08-1414:36uoslthanks for the very useful linter ^^ have you considered warning when referring to undefined bindings? I think joker did this, so I kinda miss it#2019-08-1414:43uoslactually, it seems it already does this, but it doesn't show up in my editor (neovim with ale), which I presume is because it logs as *info*.
$ echo '(defn x [] (inc z b))' | clj-kondo --lint - 
<stdin>:1:12: error: clojure.core/inc is called with 2 args but expects 1
<stdin>:1:17: info: unresolved symbol z
<stdin>:1:19: info: unresolved symbol b
#2019-08-1414:49borkdudetrue, it logs all unresolved symbols on the info level, but you can tweak that in your .clj-kondo/config.edn#2019-08-1414:50borkdudenow that this has become pretty reliable I might bump the level to :warning instead#2019-08-1414:56uoslcool! although I'm really confused why ale doesn't highlight it when it's info. I'm trying to find the setting for this, as it seems very useful to have the information#2019-08-1415:01uoslI gave up on ale for now. config.edn it is [[=#2019-08-1909:43borkdude@regen In the next release (coming this week hopefully) I will turn on the cache option by default, unless it's set to false. So a PR to ALE won't be needed anymore#2019-08-1909:44borkdudeAn idea I had is that clj-kondo could emit calls an LSP-server that collects information about defn locations, arities etc, which could then be used for editor tooling.#2019-08-1909:44borkdudeThis idea has been suggested before by other people.#2019-08-1909:47uoslIs the cache being disabled what's causing ALE to not highlight the *info* messages? I thought it intentionally ignored them?#2019-08-1909:48borkdudethese are two separate issues.#2019-08-1909:48borkdudebefore clj-kondo would only activate the cache if you said --cache true. ALE didn't pass that option#2019-08-1909:48borkdudeso you would not see arity errors across namespaces#2019-08-1909:48borkdudethe info thing: I don't know, but you can tweak the config, so that's not a big issue#2019-08-1909:55uoslok, I think you might be mixing me up with someone else, as I haven't encountered the ALE cache issue.#2019-08-1910:01borkdude@regen oh I see. you only mentioned ALE, but you didn't have that issue. but I still don't think the cache works in vim right now with ale, does it?#2019-08-1910:04uoslI haven't noticed it, but I tested it now and the issue is definitely there [=#2019-08-1920:08borkdudeI'm discontinuing the snap package. https://github.com/borkdude/clj-kondo/issues/424#issuecomment-522733274#2019-08-2009:31gordonFYI I haven't forgotten about testing https://github.com/borkdude/clj-kondo/issues/422 I'm seeing some filesystem permission errors writing the lockfile when using the cache with that binary, which I'm willing to blame on my recent upgrade to macOS Mojave until I can prove otherwise.#2019-08-2009:43borkdudecan you try to throw away the .cache directory?#2019-08-2009:56borkdude^ @gordonsyme_clojurians#2019-08-2009:59gordonI've done all the things that were obvious to me, checked permissions on binary + dir, removed the dir (it can create the cache dir fine, just can't write the lockfile), checked for macOS extended attributes.#2019-08-2010:00gordonAnyway, I'll keep poking at it and let you know when I have a result.#2019-08-2010:05borkdudeweird#2019-08-2010:06borkdudedo you maybe have some anti-virus software running? I recently had an issue with this while compiling CLJS: it became terribly slow#2019-08-2010:07borkdudein other news: clj-kondo now has a NixOS package: https://github.com/borkdude/clj-kondo/blob/master/doc/install.md#nixos#2019-08-2010:11gordonAh, I do indeed, this is my work computer.#2019-08-2010:11borkdudemaybe clj-kondo is not able to write at all then due to that malware/virus program#2019-08-2010:14gordonlein clj-kondo works fine which adds to my confusion. Anyway, I'll keep digging.#2019-08-2010:50gordonThis is an alias that invokes clj-kondo.main it turns out.#2019-08-2010:14borkdudemaybe java is whitelisted as a trusted process, but the binary clj-kondo is suspicious somehow?#2019-08-2010:14borkdudeguessing...#2019-08-2010:44gordonRunning without --cache works well enough, I don't see the recur argument mismatch any more :thumbsup:#2019-08-2010:44Macrozflycheck-clj-kondo seems to be working in my Emacs but it's not respecting ns inline config, I guess it should work?#2019-08-2010:45MacrozI'm trying to ignore some warnings but they just keep showing up#2019-08-2010:45Macrozi.e. trying something like this
{:clj-kondo/config
   '{:linters {:redefined-var {:level :off}
               :refer-all {:level :off}}}}
#2019-08-2010:46Macrozbtw it would be helpful to show the linter config key in the error tooltip#2019-08-2010:48borkdudenot all linters may work yet with the ns config. can you test with clj-kondo from master?#2019-08-2010:50Macrozyes, I'll try, the one I'm using now was https://github.com/borkdude/clj-kondo/releases/download/v2019.07.31-alpha/clj-kondo-2019.07.31-alpha-linux-amd64.zip#2019-08-2010:53borkdudeyou can run with the jvm version to test#2019-08-2010:56Macrozlooks like you have different uses and corner cases well covered 🙂#2019-08-2011:04Macrozhmm cloning the repo and running clj-kondo from there seems to give me the warnings#2019-08-2011:05Macrozso which one should work with inline config?#2019-08-2011:05borkdudedo you mean that clj-kondo from master works as desired for you?#2019-08-2011:07borkdudeif so, I can give you the binary from master#2019-08-2011:07borkdudeand then after I release the next version, you can start using it from a normal package manager again#2019-08-2011:12Macrozit doesn't#2019-08-2011:12Macrozit gives me warnings though I tried to disable them in the ns inline config#2019-08-2011:13Macrozlike the scenario from the example screenshot#2019-08-2011:13MacrozI got kondo nicely running in emacs which is good but the inline config to disable some warning sometime seemed like a good thing to get to work#2019-08-2011:14MacrozI'm wondering can I somehow test that I didn't do a stupid mistake or contribute something if it doesn't work well yet#2019-08-2011:15MacrozI don't have an open source repo here at the moment, testing on some internal code for now#2019-08-2011:16Macrozat least I can confirm that I'm running the version from master#2019-08-2011:17Macrozseems to work with --config '{:linters {:redefined-var {:level :off}}}'#2019-08-2011:17Macrozso just the ns inline config doesn't get picked#2019-08-2011:23MacrozI see you have a test like this
(is (empty? (lint! "(ns ^{:clj-kondo/config
                            '{:linters {:unused-namespace {:exclude [bar]}}}}
                          foo
                        (:require [bar :as b]))"))))

#2019-08-2011:24Macrozbut this is different example here https://github.com/borkdude/clj-kondo/raw/master/screenshots/compojure-config.png#2019-08-2011:24MacrozI can't get that to work#2019-08-2011:24borkdudePlease post an issue with the problem and repro, then I'll have a look#2019-08-2011:32MacrozI get four errors if I run lein test#2019-08-2011:32MacrozI wrote a failing test for my case and I can see if I can patch it#2019-08-2011:33Macrozbut just noticed that there are other errors too#2019-08-2011:50borkdudewithout any changes you mean? that's weird, because on CI they pass?#2019-08-2011:50borkdudecould you try with clj -A:test too?#2019-08-2012:01Macrozsame result
FAIL in (extract-clojure-core-vars-test) (extract_var_info_test.clj:12)
expected: (contains? vars (quote future))
  actual: (not (contains? #{} future))

FAIL in (extract-clojure-core-vars-test) (extract_var_info_test.clj:13)
expected: (contains? vars (quote transduce))
  actual: (not (contains? #{} transduce))

FAIL in (extract-cljs-core-vars-test) (extract_var_info_test.clj:17)
expected: (contains? vars (quote clj->js))
  actual: (not (contains? #{*target* ns js*} clj->js))

FAIL in (extract-cljs-core-vars-test) (extract_var_info_test.clj:18)
expected: (contains? vars (quote transduce))
  actual: (not (contains? #{*target* ns js*} transduce))
#2019-08-2012:26Macrozmaybe your circle build doesn't run tests?#2019-08-2012:34borkdudelet me try locally#2019-08-2012:34MacrozI see now that I need to run script/test first, without that there are some files missing#2019-08-2012:41borkdudethat's right, also what is documented in the README#2019-08-2012:42borkdudemaybe those deps can be just used to the test deps#2019-08-2012:43borkdudethey are not really used as deps, but used for extracting information#2019-08-2012:45Macrozthat part of the README is so short that it's easy to miss#2019-08-2012:46Macrozalso kind of expected to see it in the build doc#2019-08-2012:48borkdudeafaik it's not needed for building#2019-08-2012:49Macrozyes, but commonly development i.e. build, test, deploy is together#2019-08-2012:49Macrozit's not a big deal though, just something bumped into#2019-08-2012:50Macrozcould be in a contributor doc as well, or PR/issue template#2019-08-2013:57Macrozhmm it seems that you load the config "file" and use that for the filtering levels and don't use the ns local configs for filtering so it cannot possibly work#2019-08-2013:58MacrozI have always had a need to disable some linting rules locally, and it makes sense to do that in code metadata, comments or so#2019-08-2013:59MacrozI think the filtering of the results needs to be rewritten to work with the analyzer that actually resolves and propagates the local configs#2019-08-2013:59borkdudewhat exactly do you want to disable using a ns local config?#2019-08-2014:00Macrozfor example I have some redefinitions of + - etc. in one file that reimplements some math concepts#2019-08-2014:00borkdudethen you should just use :refer-clojure :exclude [+ -]#2019-08-2014:00Macrozor there is one function that does something more magic than the rest of the code ever needs to do#2019-08-2014:01MacrozI still need the core + and - in the implementation of my + and -#2019-08-2014:01borkdudeyou can refer to those as core/+#2019-08-2014:01Macrozoften I may also name something local key or value etc.#2019-08-2014:01Macrozso I naturally tried using :level :off for those reporters#2019-08-2014:01borkdudethat's fine, kondo doesn't complain about that#2019-08-2014:02Macrozmy experience is more from Java and JavaScript linters and they usually support turning off a warning here or there#2019-08-2014:02Macrozthese are just the ones I noticed when opening a random file I was working on today#2019-08-2014:02Macrozonce you have more rules there will be more cases#2019-08-2014:04borkdude
(ns foo
  (:refer-clojure :exclude [+ -])
  (:require [clojure.core :as c]))

(defn + [a b]
  (c/+ a b))

(prn (+ 1 2))
This is how you should do it in Clojure. Not using exclude while redefining things is bad.
#2019-08-2014:05borkdudeThe linters that make sense to support as namespace local configs are supported, unless someone comes up with good examples of other linters that should be supported.#2019-08-2014:05borkdudeFeel free to post an issue with good examples and we'll make it work.#2019-08-2014:06borkdudeThe reason why not everything is supported is that ns local config is a new feature and was only used for testing#2019-08-2014:06borkdudeclj-kondo has the philosophy that code should not be cluttered with tooling annotations, so where possible, use the global config#2019-08-2014:06Macrozmaybe you could just add a comment in the config section that local config does not work for every option#2019-08-2014:07borkdudeThat is already documented. > Config takes precedence in the order of namespace, command line, .clj-kondo/config.edn. *Note that not all linters are currently supported in namespace local configuration.*#2019-08-2014:08Macrozthat is different to what I mean, :level is a linter option#2019-08-2014:09borkdudeyeah, it could be documented which linters do not work with ns local config#2019-08-2014:09Macrozyour specific example in tests uses ns local config but does not support level option
(is (empty? (lint! "(ns ^{:clj-kondo/config
                            '{:linters {:unused-namespace {:exclude [bar]}}}}
                          foo
                        (:require [bar :as b]))")))
vs. a hypothetical
(is (empty? (lint! "(ns ^{:clj-kondo/config
                            '{:debug true
                              :linters {:unused-namespace {:level :off}}}}
                          foo
                        (:require [bar :as b]))")))
#2019-08-2014:10Macrozsince it's pretty clear level doesn't work then you could just mention that, I don't see a point trying to track code functionality completely in manually written documentation#2019-08-2014:10Macroztuning that quoted piece of doc would have been enough for me#2019-08-2014:11MacrozI did notice it but thought that if the linter is supported then perhaps its options are#2019-08-2014:11borkdudeah now I see what you mean. so you want a different level only for that namespace.. hmm#2019-08-2014:11borkdudefeel free to post an issue about that. I think that can work#2019-08-2014:12borkdudeI just hadn't considered that.#2019-08-2014:37Macrozthe problem in the current code is that the local configs don't get to the filter so it needs a slightly larger change than I can do myself at the moment but I'll do an issue tomorrow#2019-08-2014:47borkdudeI think the problem is that during output, the level from the global config. But you can override it I think, it's just ignored at the moment#2019-08-2014:47borkdudeso if we're luckily, it's just a minimal change. I'll look at it when I'll get to your issue#2019-08-2709:41Macroz☑️#2019-08-2010:49borkdude@gordonsyme_clojurians from the next version on, --cache will become the default so you will have to do --cache false, just as a heads up#2019-08-2010:49borkduderight now that option is interpreted as a directory, so that won't work right now
#2019-08-2010:49borkdudeor maybe it will, not sure#2019-08-2010:51gordonThanks for the warning, I need to get to the bottom of this issue, but that's a problem for me to get resolved. Thanks for being so responsive 🙂#2019-08-2109:57sogaiu@borkdude is there a way to have warnings for go-loops that don't have recurs?#2019-08-2111:30borkdudeno, because that's technically not an error#2019-08-2111:31borkdudego-loop is handled the same as loop#2019-08-2112:02borkdudeloop without recur is just a let right? yeah maybe a warning makes sense now I think about it#2019-08-2112:02borkdude^ @sogaiu feel free to suggest this in an issue so it's recorded somewhere#2019-08-2112:46sogaiu@borkdude thanks, have made an issue.#2019-08-2115:59borkdudeclj-kondo v2019.08.21-alpha Support for potemkin/import-vars, contributions from people @ #heartofclojure and more. https://github.com/borkdude/clj-kondo/releases/tag/v2019.08.21-alpha#2019-08-2210:37rickmoynihanI have a macro that introduces arbitrary new symbols within its scope. Is there a way to tell clj kondo to ignore any unused/bound symbols within its sexp?#2019-08-2210:38rickmoynihanspecifically I’d like to support the matcha query macros here for construct, ask, select etc… https://github.com/Swirrl/matcha#construct#2019-08-2210:40rickmoynihanahh is it :skip-args I need?#2019-08-2210:48rickmoynihanhmmm looks like :skip-args works but it then causes lint failures on vars that are used inside the macro (but outside its sexp) e.g.
(let [x 10 ;; x raises lint warning here
       ]
  (matcha/construct ?s [[?s ?p x]])
Inspite the fact that it is used inside matcha/construct
#2019-08-2210:50rickmoynihan:skip-args means the macros special ?s ?p symbols aren’t flagged — but it then seems to cause the usage of x not to be detected.#2019-08-2211:29yuhanI have the same issue with the meander lib which uses such special symbols all over the place - would it make sense to have a global user-customizable regex for symbols which clj-kondo will ignore?#2019-08-2211:30borkdudeyou can ignore special symbols in a macro using a config:#2019-08-2211:30borkdudehttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-unresolved-symbols-from-being-reported#2019-08-2211:31borkdude^ @rickmoynihan @qythium#2019-08-2211:35rickmoynihanyeah that’s not good enough, there is no one special symbol… you can put unbound ?symbols with names of your choosing anywhere in the macro definition.#2019-08-2211:36rickmoynihanthe macro’s implement a query engine for matching patterns in graph data#2019-08-2211:37rickmoynihanis it fair to say clj-kondo assumes that all macros behave syntactically like other common macros?#2019-08-2211:38borkdude@rickmoynihan can you give an example. I'm pretty sure you can ignore those symbols using a config.#2019-08-2211:40rickmoynihansure…#2019-08-2211:40rickmoynihan
(matcha/construct {:grafter.rdf/uri ?ds
                          ?p ?o}
                         [[catalog-uri dcat:dataset ?ds]
                          [?ds ?p ?o]])
Is from actual code… catalog-uri is bound outside the macro form in lexical scope, whilst all ? symbols are arbitrary
#2019-08-2211:42rickmoynihanor another (real usage):#2019-08-2211:44rickmoynihan
(matcha/construct {:grafter.rdf/uri ?nav-item ?nip ?nio}
                         [[nav-uri pmdui:hasNavItem ?nav-item]
                          [?nav-item ?nip ?nio]
                          (optional [[nav-uri pmdui:hasDisplayContext ?disp]])]
                         matcha-db)
here nav-uri and pmdui:hasDisplayContext and matcha-db come from lexical or ns level scope… all other symbols represent unbound query variables. The optional is nested macro syntax.
#2019-08-2211:44rickmoynihan(for which there is actually a defmacro definition, that just raises an error if it’s used outside of a query macro — but it provides a way to put a docstring on the optional)#2019-08-2211:44borkdude
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "60020f120b04150405202d222152505155"}, :content ("[email protected]")}
#2019-08-2211:45borkdudeexactly how it's documented in the doc link I just posted#2019-08-2211:46rickmoynihanahh I misunderstood what that was doing thanks, I will give it a try… but first lunch! 🙂#2019-08-2211:49borkdude#2019-08-2212:20rickmoynihanMany thanks borkdude that seems to work great!#2019-08-2213:41lreadHi @borkdude! Thanks for the new release, you’ve really created something awesome here! BTW, noticed README is still advising use of —cache in one spot: > So for lein the entire command would be: > $ clj-kondo --lint "$(lein classpath)" --cache#2019-08-2213:47borkdudeoh, that can go away 🙂 feel free to do a minor PR if you feel inclined#2019-08-2213:50borkdudeand thanks#2019-08-2213:51borkdudetotally forgot to mention you in the latest release, you helped me a bunch testing the import-vars stuff: https://github.com/borkdude/clj-kondo/releases/tag/v2019.08.21-alpha#2019-08-2214:32lreadwill do PR. And am very happy to contribute with or without mentions. simple_smile #2019-08-2218:09dharriganarch updated#2019-08-2313:28yuhanIs it possible for library authors to define linter configs for consumers of the library? Sort of the inverse of the current method of using {:clj-kondo/config '{:lint-as ...}} metadata, which has to be done manually by users on a per-project/namespace basis#2019-08-2313:32yuhanperhaps something like
(defmacro my-defn
  {:clj-kondo/lint-as `defn}
  ...)
#2019-08-2314:01borkdude@dharrigan thanks!#2019-08-2314:03borkdude@qythium that's currently not possible but that could be useful indeed. macro authors could also give some more hints to clj-kondo where they introduce new vars or bindings#2019-08-2314:08yuhanyeah, one concern would be whether it's too tightly coupled to a specific implementation - eg. Joker could use that information too but wouldn't look under a :clj-kondo/... namespace#2019-08-2314:09yuhanI recall there was some discussion before about a :tooling/.. naming convention#2019-08-2314:11borkdudeone other concern would be that some people would find it cluttering their code if they don't use a linter#2019-08-2314:11borkdudemaybe macro authors can just document this in their READMEs#2019-08-2314:11borkdudeor if they have a .clj-kondo directory, maybe clj-kondo could pick up on that#2019-08-2314:15borkdudelibrary/src/clj-kondo/config.edn <- this config will be "exported"? but then that would only work if you linted your entire classpath#2019-08-2314:15borkdudeif you would only lint your git-staged files you would already not see that config, so it might be too fragile#2019-08-2314:18yuhanah, do you mean that anything in a .clj-kondo/ directory won't make it into the exported JAR, so there would be no way to get that information if someone uses the lib as a Maven dependency?#2019-08-2314:19borkdudeeven if it would be in the jar, it would only be seen by clj-kondo if you lint your source + all your libs#2019-08-2314:20yuhanI had the impression that was what it did anyway? otherwise how does it provide arity warnings for 3rd party libs#2019-08-2314:22borkdudeI guess clj-kondo could save config information while linting libs also to the cache, but I'm not sure if that works yet#2019-08-2314:23borkdudeyou'll get the problem of the config being scattered over multiple places which can be hard to debug and understand#2019-08-2314:26borkdudeso for now it might be a good start if library authors started documenting their preferred clj-kondo config in their README#2019-08-2314:26borkdudewe can also make some command line option to generate a config file based on what is in your libraries, that might be a more transparent way#2019-08-2314:27borkdudeso if library authors exported some clj-kondo config, this command line option would gather those and add them to your config.edn#2019-08-2314:29borkdudethey could put it under libary/src/library/clj-kondo.export.edn or something#2019-08-2314:52yuhansounds like a good idea 🙂#2019-08-2314:53yuhanI wonder if a good heuristic anyway would be to ignore unresolved-symbol warnings for the 2nd position in any form that starts with def...#2019-08-2314:55yuhanthat and any symbol that starts/ends with let would probably cover a good majority of these macros#2019-08-2321:36lreadJust used clj-kondo tools to find unused vars. It sparked much joy!#2019-08-2321:37borkdude😄#2019-08-2322:20sogaiucareful, that joy-sparking could be contagious! oops, too late 😄#2019-09-0312:25juhoteperiI wonder if there is configuration to disable unused binding warning for certain names? For example, I use e (event) binding in event handler functions even I don't need the event. For new projects I could consider prefixing with _ but I'd rather not rename all bindings in existing projects. Other cases include catch Exception e, and ctx name I use for component/integrant system map.#2019-09-0312:28juhoteperiAnother thing I could use, would be to exclude unused binding warning for map destructuring :as, where I use the name for documentation, when I only refer to :keys bindings.#2019-09-0312:42borkdudeThere are only two ways to suppress these warnings: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-unused-bindings-from-being-reported There is no special option for :as but that could be implemented as a new feature.#2019-09-0510:27rickmoynihanI’m not sure why but flycheck-clj-kondo seems to only display warnings not errors, though they display via clj-kondo on the command line. I’m using the multiple linter setup with joker described here: https://github.com/borkdude/flycheck-clj-kondo#multiple-linters#2019-09-0510:42borkdudewhat output do you see when you do flycheck-compile in a buffer?#2019-09-0510:49rickmoynihanahh interesting#2019-09-0510:50rickmoynihan
clj-kondo --lint - --lang clj --cache < /Users/rick/repos/project/src/proj/routes.clj
WARNING: --cache option didn't specify directory, but no .clj-kondo directory found. Continuing without cache. See .
<stdin>:90:31: warning: unused binding imd-cfg
<stdin>:107:47: warning: unused binding decile
<stdin>:120:62: warning: unused binding params
<stdin>:136:44: warning: unused binding imd-cfg
linting took 31ms, errors: 0, warnings: 4
#2019-09-0510:51rickmoynihanso it looks like it just lints a single file#2019-09-0510:51rickmoynihanwhere as clj-kondo --lint src/ lints the whole project — and has visibility of the function var that has an arity error#2019-09-0510:52rickmoynihansorry should’ve said the specific error is an arity error#2019-09-0510:52rickmoynihanfor a function included in the project but in another namespace#2019-09-0510:52borkdude@rickmoynihan you need to make a .clj-kondo dir in the root of your project#2019-09-0510:52borkdudethen clj-kondo will create a cache where it will remember information about your vars#2019-09-0510:53rickmoynihanyeah was wondering if you’d say that 🙂#2019-09-0510:55rickmoynihanok I’d forgot you had to do this… I set it up once in another project#2019-09-0510:55rickmoynihanthanks for the pointer#2019-09-0510:55borkdudenp#2019-09-0510:56borkdudeit also seems your clj-kondo version is not the newest?#2019-09-0510:56borkdudesince I removed that warning you see above in the latest 🙂#2019-09-0511:00rickmoynihanok upgraded#2019-09-0511:01rickmoynihanI’ve mkdir .clj-kondo and when running `clj-kondo --lint “$(lein classpath)” I get the error:#2019-09-0511:02rickmoynihan#2019-09-0511:02rickmoynihan
clj-kondo --version
clj-kondo v2019.08.21-alpha
#2019-09-0511:02borkdudeNot sure what this is. Can you try to remove the .cache dir in .clj-kondo?#2019-09-0511:02rickmoynihanI did that too — same error#2019-09-0511:03borkdudedid you install clj-kondo using a package manager, if so, which one?#2019-09-0511:03rickmoynihanbrew#2019-09-0511:03borkdudeshould be good.#2019-09-0511:05borkdudewhat's weird is that I see twice the version: .cache/2019.08.21-alpha/2019.08.21-alpha#2019-09-0511:05rickmoynihanyeah I noticed that too#2019-09-0511:09borkdudecan't reproduce this locally:
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "51333e233a35243534111c130163616068"}, :content ("[email protected]")}
although the version is used twice in the cache dir, it works as expected
#2019-09-0511:09borkdudemaybe a permission thing?#2019-09-0511:11rickmoynihanI don’t think so#2019-09-0511:12borkdudeare you on Mac or Linux?#2019-09-0511:12rickmoynihanmac#2019-09-0511:12borkdudesame here#2019-09-0511:13rickmoynihan#2019-09-0511:13rickmoynihancould flycheck clj-kondo in emacs be interfering with it in the terminal?#2019-09-0511:13borkdudeso the lock file seems to be there#2019-09-0511:13borkdudethe purpose of the lock file is to ensure only one process can write the cache#2019-09-0511:14borkdudemy lock file looks this like as well: -rw-r--r-- 1 borkdude wheel 0 Sep 5 13:07 lock#2019-09-0511:15rickmoynihanessentially the same as mine#2019-09-0511:15borkdudecan you maybe try to reboot your computer? you never know 😛#2019-09-0511:16borkdudefeel free to post a repro on Github#2019-09-0511:17borkdudeyou can also try to run with lein, just for the sake of testing/debugging#2019-09-0511:18rickmoynihanok will maybe have another look at this later#2019-09-0511:19rickmoynihanthanks for your help — and for clj-kondo 🙂#2019-09-0511:19borkdudethe uberjar is downloadable from Github, also an option. java -jar ... --lint ...#2019-09-0511:19rickmoynihanahh great#2019-09-0511:20borkdudeif you want to disable the cache you can do --cache false#2019-09-0511:20borkdudegood luck and let me know if you have any new info#2019-09-0908:30borkdudeWhich companies are using clj-kondo? With your permission I want to mention you on a sheet in a presentation about it.#2019-09-0914:43gordonWe're using it quite a bit at CircleCI (thanks!) You have our permission to mention us, our marketing folks would like to have a quick look at our bit beforehand if possible, though that's not a hard requirement. Our various logos, fonts, colours etc are at https://brandfolder.com/circleci#2019-09-0914:47borkdude@UM3GAUMKP This is just going to be a slide mentioning a bulleted list of companies, not going to mention any details as time is too short for that#2019-09-0914:48borkdudeI added the logo to this issue: https://github.com/borkdude/clj-kondo/issues/438#2019-09-1020:28lreadJust had another happy session of clojure coding with clj-kondo by my side warning me of things that are amiss. A very helpful little friend!#2019-09-1223:38gerredHey all, I published a clj-kondo linter for Atom! https://atom.io/packages/linter-kondo 🎉#2019-09-1306:40borkdude@gerred awesome! If you want, a PR which adds this to the editor integration docs would be cool#2019-09-1307:16borkdude@gerred I think you are referring to linter-joker in a link, but the link says linter-joker (in the README of your package)#2019-09-1308:37borkdudeexcited...
$ echo '(subs "foo" "bar")' | clj-kondo --lint -
<stdin>:1:13: error: Expected a natural integer but received a string.
#2019-09-1311:06gerredoops, looing at my README.#2019-09-1311:06gerredoh yeah#2019-09-1311:06gerredheavily adapted by linter-joker 😄#2019-09-1311:06gerredfixing that, thanks!#2019-09-1311:09borkdudesame for flycheck-clj-kondo, 99% based on flycheck-joker. thanks @roman.bataev#2019-09-1312:05gerred@borkdude https://github.com/borkdude/clj-kondo/pull/443#2019-09-1313:05borkdude@gerred merged, thanks!#2019-09-1318:21gerredI just made a github action as well for linting with clj-kondo as a check, built right into Github Actions. If anyone here is in the beta, I'm happy to share it with you while I polish it up for release.#2019-09-1318:23gerredI'm working on having it comment on a PR review the exact lines where clj-kondo fails as well, so it's not just "fail the check, look at the logs and good luck"#2019-09-1318:23gerredthe only pain is I have to actually test it by PR-ing code that fails clj-kondo, so it's a little more geared for linting public projects that are taking in public PRs.#2019-09-1318:25borkdudeawesome idea. I'm not sure if I'm in the beta, how can I know?#2019-09-1318:27gerredhttps://github.com/features/actions#2019-09-1318:28borkdudesigned up#2019-09-1318:29gerredyou also may want to sign up for github package registry:#2019-09-1318:29gerredhttps://github.com/features/package-registry#2019-09-1318:29gerredi just finished up a workflow to release master (and soon special tags) to our github package registry docker. would be happy to help do that for clj-kondo once you're in both.#2019-09-1318:30gerreddocker hub doesn't have robot accounts and it's 😿#2019-09-1318:30borkdudesure, thanks#2019-09-1318:30gerredexample: https://github.com/kudobuilder/kudo/commit/c81392ae927ed5ebcfeea1da9c58e8848d5e4751/checks with the resultant docker image: https://github.com/kudobuilder/kudo/packages/22323?version=master#2019-09-1318:32gerredpretty handy#2019-09-1318:33borkdudeyeah, I can also do that from CircleCI, but I've resisted making releases from master until now, because people will start to depend on it 😉#2019-09-1318:33gerredyup 😄#2019-09-1318:33gerredyeah that's what we're moving from.#2019-09-1318:33gerredbecause of the integration with multiple types of GH events and the package registry.#2019-09-1318:34gerredyou can listen on any built-in GH event, like issues/pull requests, comments, everything.#2019-09-1318:34borkdudethat's pretty sweet#2019-09-1319:00borkdudehttps://twitter.com/borkdude/status/1172585439477321732#2019-09-1319:06gerredif this works how I think it does 😍#2019-09-1319:11borkdudea lot of work to be done, but conceptually it works 🙂#2019-09-1322:29borkdudeI've added a few more functions like into, map, filter, keep, etc. Anyone wanna test?#2019-09-1322:32gerredsure#2019-09-1322:37borkdudedo you prefer a binary for testing or do you want to clone the repo and run from a branch? it's relatively easy, just: clojure -A:clj-kondo --lint ...#2019-09-1322:37gerredya I'll just do that#2019-09-1322:37gerredwhat's the branch?#2019-09-1322:37gerredi have graal locally so I can even build the binary#2019-09-1322:38borkdudehttps://github.com/borkdude/clj-kondo/tree/typing#2019-09-1322:38borkdudeif you set GRAALVM_HOME, then it's just script/compile for building#2019-09-1322:39gerred👍#2019-09-1410:17borkdudeIssue where you might report findings: https://github.com/borkdude/clj-kondo/issues/445#2019-09-1410:18gerredwill do 🙂#2019-09-1410:19gerredi forgot to build it last night, building now.#2019-09-1410:20gerredis the tip of the typing branch still good or should I use a specific commit?#2019-09-1410:20borkdudejust the newest commit of the branch#2019-09-1410:20gerred👍#2019-09-1410:25gerredit'd probably help if I updated my fork from your upstream#2019-09-1410:28gerred#2019-09-1410:36gerredi may have a bad spec here but this isn't being caught:#2019-09-1410:39borkdude?#2019-09-1410:39gerredi just yanked a spec out of speculative real quick to make sure it wasn't me 😄#2019-09-1410:39gerred1s#2019-09-1410:39gerred#2019-09-1410:39gerredare you expecting that to be caught right now?#2019-09-1410:40gerredif so I'll put it in the issue#2019-09-1410:40gerredif not I won't worry about it#2019-09-1410:40borkdudeNo, you’ll have to add that spec in typing.clj in the hash map#2019-09-1410:40gerredgot it#2019-09-1410:40borkdudeIt doesn’t use fdef for reasons #2019-09-1410:41borkdudeMost particularly GraalVM issues #2019-09-1410:41gerredahh ok#2019-09-1410:42gerredah yeah I see what you're doing now#2019-09-1410:42gerredso you'd actually have to update types.clj#79 for the whole standard library if you wanted that.#2019-09-1410:42borkdudeIt’s a closed system right now but maybe in the future users can add specs in their configs #2019-09-1410:43borkdudeRight. Or at least the top most useful stuff. #2019-09-1410:44borkdudeOnly catching the single arg map/filter transducer stuff is already valuable to me#2019-09-1410:44gerredyup#2019-09-1410:44gerredyeah that's a good general list even now#2019-09-1410:44gerredi was going to suggest into then I found it 😄#2019-09-1410:45borkdudeAFK for a bit #2019-09-1416:11borkdudeAdded a bunch of functions from clojure.set and clojure.string now too#2019-09-1416:12borkdudehttps://www.dropbox.com/s/z8kujhpwm23u2i5/Screenshot%202019-09-14%2018.12.51.png?dl=0#2019-09-1419:01borkdudethe first take at local typing is merged to master#2019-09-1518:46borkdudeit can now do this as well:#2019-09-1700:43gerredhmm on master#2019-09-1700:44gerredi'm getting a bunch of "did not catch tag:" when I'm going through several libs#2019-09-1700:45gerredso for next.jdbc for example, I'm getting that on: ResultSet, DataSource, Connection, ResultSetMetaData, Integer, java.io.Writer, java.sql.ResultSet, PrepaerdStatement#2019-09-1700:46gerredit'd be nice to have a way to extend what tag-from-meta is switching over#2019-09-1706:56borkdudeyeah, sure, I forgot to delete that println#2019-09-1706:57borkdudeI'm continuing in the branch ret-types, but it's a work in progress. I'll report back here when it's a good time to check again!#2019-09-1709:22borkdudethe branch ret-types can be tested.#2019-09-1709:47borkdudeI have to clean up that branch some more, and then I'll merge to master#2019-09-1710:11gerred👍#2019-09-1710:14borkdudebut you can test it right now if you want 🙂#2019-09-1710:18gerredoh why not 😄#2019-09-1710:18gerredneed to make sure it works with linter-kondo anyway, right? 😉#2019-09-1710:41borkdudeone issue I struggled with is that ^String can be nilable, but some specs I wrote expected just a ::string. But to not create any false positives, I basically have to treat almost every type a nilable.#2019-09-1710:42borkdudethat's why (subs nil 1 10) now doesn't create a warning#2019-09-1710:43borkdudeit sucks, but at least you still get warning for (subs 1 2 3)#2019-09-1710:43gerredoh sure#2019-09-1710:43gerredthat's fair.#2019-09-1718:14robertfwIt appears that within cond->, I'm not seeing unresolved symbol errors. I took a look through the issues on github but didn't spot anything related - is this a known problem, or would you like me to file a bug?#2019-09-1718:15robertfw#2019-09-1718:36robertfwAppears to be both within the condition and the body#2019-09-1718:37robertfw#2019-09-1721:57borkdude@robertfrederickwarner That's known, some macros aren't fully linted, because I just didn't get around to it yet. Will handle it in a future version.#2019-09-1721:57borkdude@gerred I think the nil issue has been fixed now in the ret-types branch. Still have to do some cleaning/maybe optimizing#2019-09-1721:58borkdude
$ echo '(subs nil 1 1)' | clj-kondo --lint -
<stdin>:1:7: error: Expected: string, received: nil.
linting took 10ms, errors: 1, warnings: 0
#2019-09-1821:27borkdudejust fyi, I have ditched spec and working on my own "spec" format. it's much faster and less powerful, but ok enough for this purpose. I want to allow users to provide their own function types (like C headers maybe) in the config. it would look a bit like:
'map {:arities {1 {:arg-tags [::ifn]
                      :ret-tag ::transducer}
                   :varargs {:arg-tags '[::ifn ::seqable (* ::seqable)]
                             :ret-tag ::seqable-out}}}
work is in progress in the ret-types branch
#2019-09-1821:27borkdude(the format will change, just the general idea)#2019-09-1821:37borkdudeThese are the types for assoc which will allow catching an uneven amount of args:
:arg-tags '[::nilable-associative ::any ::any (* [::any ::any])]
$ echo '(assoc {} 1 2 3)' | clj-kondo --lint -
<stdin>:1:15: error: Insuffient input.
#2019-09-1822:05robertfwIs spec that difficult of a target to work with? We have s/fdefs for any of our publicly facing functions and it'd be great to have something that ties into that#2019-09-1822:09borkdudeI bet there's more sources that can be used to derive data that clj-kondo can work with, e.g. schema.core/defn#2019-09-1822:09borkdudeyour fdefs can refer to other specs in another place in your code base, that's at least one challenge#2019-09-1822:22lilactownspec is just not really designed for static analysis. I think if it were, it would look quite different#2019-09-1902:05robertfwI suppose the fact it is being overhauled right now also makes it a bit of a moving targret#2019-09-1902:06robertfwLook forward to seeing what you come up with 🙂 kondo is a fantastic tool, thank you for your work on it#2019-09-1906:28borkdudeon the ret-types branch using this config:
:type-mismatch
{:level :warning
 :vars {clj-kondo.core/print! {:arities {1 {:args [:map]
                                            :ret :nil}}}
        clj-kondo.core/run! {:arities {1 {:args [:map]
                                          :ret :map}}}}}
$ echo "(require '[clj-kondo.core :as clj-kondo]) (clj-kondo/run! nil)" | clj -A:clj-kondo --lint -
<stdin>:1:59: warning: Expected: map, received: nil.
#2019-09-2120:12borkdudehttps://github.com/borkdude/clj-kondo/blob/master/doc/types.md#2019-09-2120:20borkdudeplease give it a go if you're interested#2019-09-2120:49borkdudeThe easiest way to try this out may be the uberjar: https://5965-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.08.22-alpha-SNAPSHOT-standalone.jar Run it with java -jar ... --lint ...#2019-09-2121:24sogaiuhow about trying to generate the type annotations based on observed execution?#2019-09-2121:34borkdudethat's another research project of it's own I think? 🙂#2019-09-2121:35borkdudeit's nice to get things for free, but a linter also wants to err on the side of false negatives#2019-09-2200:26sogaiui was thinking it would help to get people to try the feature out -- not too keen on having to write the annotations from scratch, but may be the barrier-to-entry might be sufficiently low if all i needed to do was edit some generated things 🙂 he he -- just being lazy#2019-09-2206:36borkdudeYeah, spec provider might be used to generate an initial config. This can be a third party tool outside of clj-kondo#2019-09-2207:53sogaiui wonder if it's practical to generate the annotations for clj-kondo from at least some types of existing specs#2019-09-2207:54sogaiumay be there's a way to automate getting part-way there -- and fill the rest in with core.logic? i can dream, can't i 🙂#2019-09-2209:33borkdudefeel free to experiment 🙂#2019-09-2211:42Marc O'Morain🙏#2019-09-2211:54glenjamin👋 Just wanted to expand on the success story @marc-omorain mentioned: This is an extracted code sample that represents what i actually had
(defn- make-api-call
  "Separate the logic from the call mechanism, even though there's only one call"
  [{:keys [api path body tags]}]
  (let [metric-result (promise)
        metric-status (promise)]
    (try
      (let [{:keys [status]}
            (clj-http.client/post ""
                                  {:form-params body})]
        (deliver metric-status status)
        (deliver metric-result :ok))
      (catch clojure.lang.ExceptionInfo ex
        (let [data (ex-data ex)]
          (when-let [status (:status data)]
            (deliver metric-status status)
            (deliver metric-result :http-error)
            (throw (ex-info "request failed"
                            (merge data {:api api
                                         :type :http})
                            ex)))
          (deliver metric-result)
          (throw ex)))
      (catch java.io.IOException ex
        (deliver metric-result :io-error)
        (throw (ex-info "connection failed"
                        {:api api
                         :type :transport}
                        ex)))
      (catch Throwable ex
        (deliver metric-result :error)
        (throw ex)))))
and this is the error clj-kondo found that i’d overlooked
error: wrong number of args (1) passed to clojure.core/deliver
My tests didn’t exercise that path, because it probably shouldn’t ever happen in practice.
#2019-09-2211:56borkdudeah, makes sense. thanks 🙂#2019-09-2211:57borkdudeThis is the slide I've made out of it. Have to keep it brief, because I have only 20 minutes, so I'm going to mention it in passing. https://www.dropbox.com/s/mcptwz75u6bqcgz/Screenshot%202019-09-22%2013.57.24.png?dl=0#2019-09-2212:05glenjaminon a different note, is this scenario something that kondo could/should catch?
(deftest does-some-stuff
  (testing "it does-some-stuff"
    (let [path "resources/test/some/stuff"]
      (= (keywordize-keys (yaml/parse-string (slurp (str path "/config.yml"))))
         (do-stuff path {:parameters {:option false}})))))
#2019-09-2212:06borkdudeyeah, it could. right now it only catches that if you use the predicate directly under deftest, but it could be made more intelligent#2019-09-2212:07borkdudeit always comes at a trade off of producing false negatives.#2019-09-2212:08borkdudefeel free to produce an issue on Github so I don't forget about it#2019-09-2212:09glenjaminwill do 👍#2019-09-2221:41borkdudeclj-kondo v2019.09.22-alpha Type checking and more. https://github.com/borkdude/clj-kondo/releases/tag/v2019.09.22-alpha#2019-09-2305:33tatutthis type checking stuff is very interesting… especially for libraries to have them#2019-09-2305:34tatutare there some plans to have a “shared place” from where clj-kondo will discover type information?#2019-09-2305:35tatutlike a database of “function sha -> type signatures”#2019-09-2305:47dominicmI'm interested in a project wide lint: are all namespaces aliased consistently. I currently couldn't build this on the analysis cache (no alias information) and also kondo has no notion of project. Should I be going this alone, or is the scope of kondo open to change for these things?#2019-09-2306:22borkdude@dominicm clj-kondo has analysis data export. Aliases can be added to that. Then it’s only a matter of only linting your project sources to discover consistency.#2019-09-2306:24borkdude@tatut libraries could provide their annotations as config and clj-kondo could somehow pick up on this. One caveat: I haven’t fully figured out the right config format yet, so things might change#2019-09-2306:27borkdude@dominicm feel free to create a PR or issue #2019-09-2307:14borkdude@dominicm I was referring to this: https://github.com/borkdude/clj-kondo/tree/master/analysis The cache is an implementation detail that you should't really rely on as a user#2019-09-2307:29dominicmah, that makes more sense.#2019-09-2307:52dharriganarch updated.#2019-09-2307:54dominicm@borkdude opened a PR! That was super easy. Something really key was spotting that I could run the analysis in the repl (copied from some of the examples). I assumed I'd have to run the cli via deps.edn and inspect the resulting file.#2019-09-2307:56dominicmJust curious, it would be pretty cool to run a linting pass by providing programs to clj-kondo to run. Maybe sci programs? The output would be some data shape which clj-kondo would use to produce messages.#2019-09-2308:11borkdude@dharrigan thank you#2019-09-2308:17borkdude@dominicm Thanks. Can you move the :as down as an argument to assoc-some? That way it doesn't end up in the EDN if it's nil. Can you also update the tests so this will be tested?#2019-09-2308:20borkdudeAbout your idea: I'm not sure if I understand it.#2019-09-2308:39dominicmMaybe it doesn't make sense. I was just thinking about the fact that to get my linter setup I have to figure out graalvm, I have to release binaries, etc. etc. It would be really cool if I could just upload a sci gist somewhere and have people attach it to their existing clj-kondo process.#2019-09-2308:40borkdude@dominicm do you mean something like https://clj-kondo.michielborkent.nl but as an API?#2019-09-2308:43borkdudeFeel free to sketch out a scenario/example, since it's still not entirely clear to me, but it sounds interesting already 😉#2019-09-2308:46dominicmNo. I mean that clj-kondo would use sci to generate additional lint warnings. e.g. the missing docstrings example in the analysis folder. So you perhaps would stick some files in .clj-kondo/linters/*.sci, and clj-kondo would execute them each with the analysis available (maybe bound to clj-kondo.foo/*analysis*) and the result of the program would be data like:
[{:line 10 :column 20 :message "missing docstring" :type :warning}]
Which clj-kondo would then format into messages and append to the messages output.
#2019-09-2308:47borkdudeah like hooks#2019-09-2308:48dominicmKinda, yeah. Although hooks usually imply several points at which you might "override" a behavior (e.g. pre-analysis, pre-parse, etc.). This is essentially a way to provide custom linters to clj-kondo.#2019-09-2308:49borkdudeah, so instead of writing your own program on top of the analysis, clj-kondo will use sci snippets to emit extra warnings. yeah, that could work#2019-09-2308:51dominicmYeah. Exactly. The intention being that it's quite a high barrier if you just want to add one or 2 little linters on top of clj-kondo.#2019-09-2308:52borkdudeIt's a cool idea. I would say store this idea in a Github issue so we can chew a little bit on it#2019-09-2308:52dominicmGreat 🙂#2019-09-2308:53borkdudeI don't know what the performance impact of emitting the analysis output is. For this feature it would have to be always on. Maybe it's neglectible and it would be ok.#2019-09-2308:55borkdudeAlso when you edit only one file, the sci program would only see the analysis for that one file.#2019-09-2308:55borkdudeAnd for most analyses it's more interesting to see the output of the entire project/source dir#2019-09-2308:57borkdudeAlso executing sci programs could potentially slow down the linter#2019-09-2308:57borkdudeThis can be easily tested by writing some babashka scripts (which uses sci) on top of some analysis#2019-09-2308:59borkdudeAt least people already have a way of making their own linters (like you wanted with the aliases) and they can run it in CI every so often#2019-09-2309:00dominicmYeah. It's cool that it's an option 🙂 Don't get me wrong. But I know that I have to get people to set it up in their tooling, and write emacs/vscode/etc plugins. It's a lot of work!#2019-09-2309:00dominicmRE emitting the analysis, do you mean to disk, or to memory? The sci scripts would only need to operate on the in-memory analysis.#2019-09-2309:01dominicmAlso. Isn't the analysis cache available, which would serialize data from other namespaces and make it available to the sci script?#2019-09-2309:01borkdudeemitting in memory so it will be printed by clj-kondo#2019-09-2309:03borkdudeThe cache is consulted only specifically when you are requiring namespaces that clj-kondo wants to know something about. It's very expensive (like 1 second, depending on how many libs you have cached in there) to read all of the cache into memory, I put effort into this to make it as fast as possible by only loading the necessary data.#2019-09-2309:03borkdudeThat's why I think most analyses are better off as a custom tool outside of clj-kondo probably#2019-09-2309:04borkdudeAnd if these analyses are very useful, they can eventually end up as a built-in linter#2019-09-2308:23borkdude@dominicm The tests for it are here: https://github.com/borkdude/clj-kondo/blob/master/test/clj_kondo/analysis_test.clj#2019-09-2309:25borkdudeLast chance to get your company logo in this sheet for ClojuTRE: https://twitter.com/borkdude/status/1176064888080351235#2019-09-2309:31borkdude@dominicm Maybe juxt?#2019-09-2309:37dominicmWe do use it on some client projects. If that's enough to make the list, feel free to include us :)#2019-09-2310:16borkdudeyeah, only one person is enough 😉#2019-09-2310:17borkdudeMade a small tweak to your PR#2019-09-2311:06borkdude@dominicm One other idea would be (since you mentioned the REPL use) is to run that analysis in the tests of your project and throw/print a warning when people use different aliases. Tests are ran by developers locally right? 😉#2019-09-2311:30dominicmWhat's a test?#2019-09-2311:30borkdudeunit test#2019-09-2311:32dominicmSorry, I was joking :)#2019-09-2311:33borkdudeha...ha... 😉
#2019-09-2311:30borkdudeclojure.test/deftest#2019-09-2311:31dominicmYeah. Could fail a test. That tends not to be set up quite in the same way as tests are though.#2019-09-2311:32borkdudeYou could make the test just emit warnings. And using it as a test, you could keep clj-kondo outside the normal deps.#2019-09-2311:34borkdudeEmit warnings and hang for 5 seconds. That's a strategy I recently read when someone deprecated something 😉#2019-09-2314:05borkdudePSA: clj-kondo has an invalid type for the third param of partition. This can be worked around as follows: https://github.com/borkdude/clj-kondo/issues/470 Will be fixed in the next release.#2019-09-2314:26Marc O'Morain#2019-09-2314:27borkdude@marc-omorain did kondo find a "missing test assertion", or what was going on there?#2019-09-2314:35glenjaminthere’s a definite line between us making kondo look good and kondo making us look like amateurs 😞#2019-09-2314:36borkdudeI made kondo because I didn't want to look like an amateur when checking in inline defs, so welcome 😛#2019-09-2314:36glenjaminoh wow, the filename and the namespace declaration didn’t match#2019-09-2314:37borkdudeah, that makes sense. that could probably be a linting rule#2019-09-2314:37borkdudedid it have to do with underscores?#2019-09-2314:46glenjaminat a guess i’d say the file was renamed at some point and the namespace had the old name - and because it was a test file, it was only ever implicitly loaded#2019-09-2314:49borkduderight, leiningen didn't complain while loading the file?#2019-09-2507:03Saikyun@borkdude what paths are actually needed for clj-kondo? 🙂 see this: https://github.com/thheller/shadow-cljs/issues/558#event-2643788138#2019-09-2507:03Saikyunthheller asked: > Does clj-kondo really require the full classpath? Wouldn't the actual :source-paths suffice?#2019-09-2507:04SaikyunI thought clj-kondo wanted all the things, but I don't know#2019-09-2507:12borkdudeIt depends. If you lint your libraries then clj-kondo knows about arities and other information about library functions. If it doesn't know about them, it won't emit warnings when you call them incorrectly.#2019-09-2507:14Saikyunokay, thanks. so then it is useful to cache your libraries as well 🙂#2019-09-2507:14borkdudeyes#2019-09-2507:22Saikyunthanks!#2019-09-2511:27sogaiu@borkdude i'm investigating the idea of generating TAGS / tags files using clj-kondo analysis data, but iiuc, there are few pieces of info that don't get picked up (or stored at any rate). the motivation is that, iiuc, clj-kondo understands clojure source better than the various ctags implementations so it ought to be able to index better. the two thoughts that come up are: 1) using the analysis data, revisit all of the relevant files to collect the info -OR- 2) is there some way to hook into / customize clj-kondo's process of visiting files so that the data might be collected in a customized fashion? the missing pieces for the etags version of TAGS are, iiuc, for each identifier: * some text preceding the identifier (as well as the identifier) also get stored separately from the identifier. e.g. for a namespace clojure.core, that text might be:
(ns ^{:doc "The core Clojure language."
       :author "Rich Hickey"}
  clojure.core
for a function definition for start, it might be:
(defn start
* the byte-offset of the beginning of that text from the beginning of the file it lives in cf: https://en.wikipedia.org/wiki/Ctags#Tags_file_formats (i haven't really digested what's needed for the other ctags tags formats yet as my initial interest is getting something working with emacs.) any thoughts?
#2019-09-2511:33borkdudeI'll take a look later, I'm on a plane right now and can't visit many links. Please document what is required to the analysis output in a GH issue#2019-09-2511:40sogaiutnx, will do#2019-09-2605:53borkdude@tatut I could have sworn that you posted an issue somewhere about warn about (< 1) etc, but I can't find it anymore#2019-09-2605:57tatutI commented on the (= 1) issue#2019-09-2605:58tatutBecause it’s the same issue basically#2019-09-2605:59borkdudeThank you!#2019-09-2617:34borkdude@sogaiu I made an issue for a bug you referred to in relation to jet, but it was actually one in clj-kondo: https://github.com/borkdude/clj-kondo/issues/476#2019-09-2711:01martinklepsch#2019-09-2711:01martinklepschclj-kondo at ClojuTRE!#2019-09-3009:45borkdudehttps://twitter.com/borkdude/status/1178606712389062657#2019-09-3010:45sogaiui'm looking at the analysis export in the var-usages section -- one of the map entries i see is roughly like:
{:filename "src/augistints/src/augistints/gen.cljc",
 :row 11,
 :col 17,
 :from augistints.gen,
 :to rewrite-clj.zip,
 :name string,
 :arity 1,
 :lang :clj}
i looked in the source file and what i see on row / line 11 is:
(let [fn-name (rz/string (:fn-name studied))]
there is the following bit in the ns declaration at the top of the file:
[rewrite-clj.zip :as rz]))
so it looks like the analysis data doesn't retain the alias info within the map entry in this case (though perhaps the info about rz == rewrite-clj.zip is retained elsewhere in the analysis info). is there a way to get it to do that? is it correct that there's no way currently to distinguish between occurrences of: 1) rewrite-clj.zip/string 2) rz/string without visitng the file to check?
#2019-09-3010:46borkdudethe alias is included in other parts of the analysis information so you might be able to get it like that.#2019-09-3010:47sogaiuwas just hoping i could get clj-kondo to do it 🙂#2019-09-3010:47borkdudewhy do you need this?#2019-09-3010:48sogaiuin emacs, the default M-. behavior detects namespaces so i wanted to create indices where the identifiers can also have ns / alias info with them.#2019-09-3010:48sogaiuthen i don't need to give instructions to override emacs behavior to throw away ns info.#2019-09-3010:48sogaiuit also means less extra defs to comb through in results.#2019-09-3010:49borkdudeah so you want to go from rz/string to the file with namespace rewrite-clj?#2019-09-3010:49sogaiuyes, to rewrite-clj.zip or other relevant#2019-09-3010:50borkdudecan't you look in the used-namespaces to look up the alias?#2019-09-3010:54sogaiui may try doing that -- there are a few things about that, possibly minor: 1) indexing will likely be slower (not sure how much, so may be once i do it, i'll have a better idea) 2) i can't distinguish from the analysis data whether the occurence is rewrite-clj.zip/string or rz/string without visiting the file -- may be that's not important though#2019-09-3010:55sogaiuto address the second point, i guess i can throw in extra index entries for every non-ns-prefixed entry -- so the index may grow in size#2019-09-3010:56sogaiuin any case, i can try out an implementation first and see i suppose#2019-09-3010:58borkdudefrom this:
:namespace-usages [{:filename "<stdin>",
                                :row 1,
                                :col 20,
                                :from foo,
                                :to clojure.set,
                                :alias set}]
you can make a map from filename to namespace name + alias
#2019-09-3010:58borkdudeor any other shape you need#2019-09-3010:58sogaiuah, so i can distinguish then#2019-09-3010:58borkdudeyes#2019-09-3010:59sogaiuok, thanks for straightening me out 🙂#2019-09-3010:59borkdudebut I guess adding the alias to the var usage would also be fine, maybe call it :to-alias or something#2019-09-3011:00sogaiuthat would be nice 🙂 but i'm ok to try what you suggest in any case#2019-09-3011:00borkdudebut for now I guess using :namespace-usages will be fine maybe#2019-09-3011:01sogaiuah, also, i noticed that things that use (alias ...) and not require :as, don't seem to get picked up in the same way.#2019-09-3011:01borkdudeyeah, I noticed that too. same for (require ...)#2019-09-3011:01borkdudefix welcome#2019-09-3011:02sogaiuhe he -- hopefully i'll learn enough about clj-kondo that that will be manageable before long 🙂#2019-09-3011:02borkdudeit's just data processing -- and there are already many other places where this data is emitted, so you can just imitate that if you're interested in doing a fix.#2019-09-3011:06sogaiuah, if it's not too much trouble, would you mind pointing me at specific functions / lines of an example or two?#2019-09-3011:09borkdudeSure. These are the functions through which all the data flows that ends up in the analysis export: https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/analysis.clj So you can grep for wherever these functions are called.#2019-09-3011:10borkdudeOne thing that bugs me is that I spelled :var-args-min-arity not like :varargs-min-arity.#2019-09-3011:13sogaiuthanks!#2019-09-3011:14sogaiui don't rely on that, so have no problem with that changing 🙂#2019-09-3011:14sogaiueven if i did, i'm happy to adjust#2019-09-3011:16borkduderight, I don't think a lot of people depend on this yet#2019-09-3011:17sogaiubetter change it soon as you mentioned the analysis export it in your talk 🙂#2019-09-3011:18borkdudehttps://github.com/borkdude/clj-kondo/issues/478#2019-10-0104:27maxpHow to make clj-kondo handle mount.core/defstate macro correctly? :lint-as something?#2019-10-0104:29maxp(defstate my-state :start ... :stop ...)#2019-10-0107:13borkdude@maxp you can try {:lint-as {mount.core/defstate clojure.core/def}}#2019-10-0107:13maxpthank you, it works.#2019-10-0111:35genmeblogIs it possible to have one clj-kondo config for all projects (eg. in home directory)? I have set of macros which cause an arity false positive error. I don't want to add exclusion for each and every project which uses it.#2019-10-0111:36borkdude@tsulej the binary accepts a --config flag which you can use for bringing in additional config. maybe that works for you?#2019-10-0111:36borkdudeit's a little bit discouraged to scatter config over multiple places because it should ideally be in the same git repo as your code, so your collaborators don't have to re-invent that#2019-10-0111:38genmeblogYou're right in general. But in my case I have a bunch of clojure2d sketches here and there as separate projects and they all are filled with kind of threading macros (there are two actually).#2019-10-0111:38genmeblogSo they are my personal projects.#2019-10-0111:39genmeblogMaybe the other option: I work with emacs and flycheck, how to feed flycheck with custom config then?#2019-10-0111:40borkdudeyou can can call (flycheck-clj-kondo-define-checkers "--config" "your-config.edn")#2019-10-0111:40borkdudeit's not documented but I think that should work.#2019-10-0111:40borkdudehttps://github.com/borkdude/flycheck-clj-kondo/blob/353e3481a20fbd577ad79db8bbc6113ce179c195/flycheck-clj-kondo.el#L79#2019-10-0111:40genmeblogperfect, let me check#2019-10-0111:45borkdudethe --cache option is no longer needed, it has become the default. so you can leave that out#2019-10-0111:52genmeblog@borkdude now I'm getting
Suspicious state from syntax checker clj-kondo-clj: Flycheck checker clj-kondo-clj returned non-zero exit code 124, but its output contained no errors: Unexpected error. Please report an issue.
java.lang.ClassCastException: java.lang.String cannot be cast to java.io.File
	at clj_kondo.impl.core$read_edn_file$fn__4643.invoke(core.clj:51)
	at clj_kondo.impl.core$read_edn_file.invokeStatic(core.clj:51)
	at clj_kondo.impl.core$resolve_config.invokeStatic(core.clj:62)
	at clj_kondo.core$run_BANG_.invokeStatic(core.clj:83)
	at clj_kondo.main$main.invokeStatic(main.clj:85)
	at clj_kondo.main$main.doInvoke(main.clj:78)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:665)
	at clj_kondo.main$_main$fn__4787.invoke(main.clj:104)
	at clj_kondo.main$_main.invokeStatic(main.clj:104)
	at clj_kondo.main$_main.doInvoke(main.clj:102)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clj_kondo.main.main(Unknown Source)

Try installing a more recent version of clj-kondo-clj, and please open a bug report if the issue persists in the latest release.  Thanks!
when using config containing
{:linters {:invalid-arity {:skip-args [clojure2d.core/with-canvas->
                                       clojure2d.core/with-canvas]}}}
#2019-10-0111:53genmeblogand line in my init.el (flycheck-clj-kondo-define-checkers "--config" "~/.emacs.d/clj-kondo-config.edn")#2019-10-0111:54borkdudeI think clj-kondo doesn't interpolate ~ but maybe you can fix that using some emacs lisp wizardry#2019-10-0111:54genmeblogok#2019-10-0111:56genmeblogyeah! works 🙂#2019-10-0111:56borkdude😄#2019-10-0111:56genmeblogthank you for quick support#2019-10-0117:25danielcomptonBringing back https://github.com/borkdude/clj-kondo/issues/241#issuecomment-507370830#2019-10-0117:28borkdudewhat about it?#2019-10-0117:28danielcomptonNot sure if this is up for discussion, but wondering if this would be a better way to show side-effects?
(ns foo
  (:require foo.specs ;; <-- leave as is
            [bar.utils :as bu] ;; <-- unused, free to remove
    ,,,))
#2019-10-0117:29borkdudeThat would be against "how to ns" advice. Also it's not what most people are already doing.#2019-10-0117:29borkdudeThis option has been suggested in that thread and maybe had some other drawbacks that I can't remember off the top of my head right now.#2019-10-0117:31borkdudeOne thing was maybe that in CLJS you can have strings for ns names and maybe that didn't work outside a vector or something. Not sure#2019-10-0117:31danielcomptonNo problem, couldn't see that in the thread when I scanned but that makes sense#2019-10-0117:32borkdudeI think capturing what most people already seem to be doing is best for a linter, since adoption will be less painful#2019-10-0118:25mynomotoI think @danielcompton example works. clj-kondo doesn't complain about naked requires as in (:require clojure.string) produces no warnings. I use that convention on my projects.#2019-10-0119:06dominicmI use non aliased requires all the time, I still want them marked if they're not in use.#2019-10-0119:22mynomotoIt's hard to please everyone. I remember the thread where this was discussed. It was long an full of opinions.#2019-10-0119:24mynomotoI wonder if unused-symbols could be a :warning by default. It's the only :info on default configuration and Ale doesn't show that on vim 😕 and there is no way to have a global config for clj-kondo afaik.#2019-10-0119:24mynomotohttps://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/config.clj#L39#2019-10-0120:11borkdude@mynomoto PR welcome to bump it to :warning. I was planning to anyway#2019-10-0120:17borkdude@dominicm you can have it your way with {:linters {:unused-namespace {:simple-libspec true}}}.#2019-10-0120:22mynomoto@borkdude will do, thanks.#2019-10-0218:00Hannu HartikainenI feel I’m starting to somewhat understand the type checking. What’s the reason to keep :seqable-out separate from :seqable, though?#2019-10-0218:36mynomoto@borkdude could you please release a new version? I want to update to the latest but the false positives on types for partition and conj are stopping me.#2019-10-0218:55borkdude@mynomoto There's one last bit I want to tweak about a new linter and then I'll release#2019-10-0218:55borkdudeThe challenge with the new unused-private-var linter is that some private fns defined in .cljc/.cljs may be used in .cljs/.cljc, so it's not just a matter of checking all defs/calls in one file#2019-10-0219:02borkdudeI guess joker also just does that, since it lints one file at a time. So maybe it would be OK if you could exclude certain private fns from being reported#2019-10-0219:04borkdude@hannu.hartikainen The reason for seqable-out is that I want to exclude nil and string that are normally seqable. So you should not rely on a seqable-out function to be able to produce nil or a string#2019-10-0219:05borkdudethis leads to better error messages#2019-10-0219:06Hannu Hartikainen@borkdude good to know. There’s already a bug with next and the functions that use it, then 🙂#2019-10-0219:06borkdudesince you might have an argument type where nil could be a valid value and then seqable would match, while the non-nilable variant of that type could not be a seqable at all#2019-10-0219:06borkdudecan you show an example please#2019-10-0219:08Hannu Hartikainenit’s just that next can return nil#2019-10-0219:15borkdudeI don't think that will lead to a false positive in practice. Excluding string is probably the most pressing reason, to still be able to output errors like:
$ clj -A:clj-kondo --lint - <<< '(defn foo [^String _x]) (foo (next [1 2 3]))'
<stdin>:1:30: warning: Expected: string or nil, received: seqable collection.
#2019-10-0219:16borkdudeif next produced a seqable it COULD produce a string, so this would be valid#2019-10-0219:18borkdudeit sounds a bit confusing I know, but I think starting with a false positive is better than just changing it#2019-10-0219:20borkdudea seqable-out is a seqable and when you call next you expect a seqable back, so that mostly works. there aren't any functions expecting explicitly a nil value.#2019-10-0219:23borkdudeif you can come up with an example where this doesn't play out, I'd be curious.#2019-10-0219:32Hannu Hartikainenyes, that’s absolutely true#2019-10-0219:34Hannu Hartikainenbut when in the future someone extends the type system to give warnings of missing nil checks, that wrong type will cause false negatives#2019-10-0219:35Hannu Hartikainenso it’s not very worrying but I’ll change to :nilable/seqable-out someday… not today though#2019-10-0219:46borkdudeI guess making seqable-out contain nil will probably work out everywhere btw, but not doing that has probably the same effect in terms of linting, since there are no functions requiring an explicit nil anywhere#2019-10-0219:47borkdudebut turning next into seqable -> seqable (instead of seqable-out) will stop this from warning:
clj -A:clj-kondo --lint - <<< '(defn foo [^String _x]) (foo (next [1 2 3]))'
linting took 82ms, errors: 0, warnings: 0
Just tried that. So let's forget about what I said about nil, seqable-out is about excluding strings.
#2019-10-0219:51borkdudeThere is more to this "type system" that's not always telling the truth for a 100%, but it's made with linting in mind. Like:
$ clj -A:clj-kondo --lint - <<< '(reduce 1 1 1)'
<stdin>:1:9: warning: Expected: function, received: positive integer.
<stdin>:1:13: warning: Expected: seqable collection, received: positive integer.
Actually reduce expects a reducible, not a seqable. But in practice this works well enough so far.
#2019-10-0220:20borkdude@mynomoto if you want to use the latest, you can do that and turn the type checking off like any other linter. or override the types for problematic functions in your config. like so: https://github.com/borkdude/clj-kondo/issues/470#2019-10-0220:20borkdudebut I expect a new release within a few days hopefully (no promises)#2019-10-0221:34borkdude@mynomoto oh, and if I can make you happy with a binary from master, I think you were using linux right? https://6255-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.09.23-alpha-SNAPSHOT-linux-amd64.zip#2019-10-0222:11mynomoto@borkdude I will try it thanks, but to run on ci I need a proper release. I'm happy to wait, if I do configuration to ignore something it tends to be forgotten 😕#2019-10-0222:16borkdudeare you running with a binary or from java in CI?#2019-10-0222:24mynomotobinary#2019-10-0222:26borkdudethat's fine. in CI you could also use deps.edn and then use a commit SHA, if you don't want to wait for the next binary#2019-10-0222:33mynomotoI can wait, but thanks for the options. Test worked, all false positives are gone. Thanks!#2019-10-0308:24borkdudeI've merged the final thing I wanted to get in for the next release. If you can give it one more try later today, then I'll make a release if there are no other problems. @mynomoto: Linux: https://6280-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.09.23-alpha-SNAPSHOT-linux-amd64.zip#2019-10-0308:24borkdudeFor Mac users: https://6281-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.09.23-alpha-SNAPSHOT-macos-amd64.zip#2019-10-0311:55tatuthttps://github.com/borkdude/clj-kondo/issues/496 <- this may be very tricky because core.match looks like a quite complicated macro#2019-10-0311:56tatutadded an issue to track it, couldn’t find previous issues about core.match#2019-10-0311:58borkdudeOK. For now you can use the config to turn linting off inside that macro.#2019-10-0311:58tatutwell maybe a 1st approximation would be to just consider all non-quoted symbols in the pattern part to be available in the consequent part#2019-10-0311:59borkdudeRight. It is possible to implement, no doubt, but just pointing at a workaround for now.#2019-10-0311:59borkdudeThanks for posting the issue.#2019-10-0312:00borkdudeI will def. consider it as it's a common thing in the ecosystem.#2019-10-0312:00borkdudeIf you want you can also start working on a PR.#2019-10-0312:00borkdudeBut if I don't notice any activity, I will probably do it at some point.#2019-10-0312:01tatutok, maybe… I’ve been thinking about trying my hand at implementing something to clj-kondo#2019-10-0312:01borkdudeI think you can draw some analogies from linting the let macro.#2019-10-0312:01tatut:thumbsup:#2019-10-0312:57mynomoto@borkdude testing it.#2019-10-0313:37tatutwhat aliases should I use with cider-jack-in, having trouble running clj-kondo.main-test from cider#2019-10-0313:48borkdude@tatut I start it like clj -A:test:cider-nrepl from the command line. I never use cider-jack-in because I'm old fashioned. I connect with cider-connect.#2019-10-0313:49tatutok#2019-10-0313:49tatutI got it running and made a new corpus/core_match/match.clj with the failing case and added a test to main_test.clj which now fails#2019-10-0313:49tatutthen the harder part of implementing#2019-10-0313:50borkdudegood start#2019-10-0313:50tatutIf I understand this correctly, I would add to the (case [resolved-as-namespace resolved-as-name] case in analyzer.clj#2019-10-0313:50borkdudecorrect#2019-10-0313:51tatutok, I’ll see what I can do#2019-10-0313:52borkdudeas I've already mentioned, the let linting is probably similar. maybe also the core.async alt macro#2019-10-0313:52borkdude(I can never remember if that should be plural and with or without exclamation marks and how many)#2019-10-0313:53tatutI’m unclear what I should return, but I’ll fire up the cider debugger and inspect things#2019-10-0313:53tatutand look at what let and others are doing#2019-10-0313:54borkdudewhat you should do to prevent false positives: extract the bindings from the form that introduces them, add them to the ctx under :bindings and then lint the children nodes using that ctx#2019-10-0313:56tatutcider debugger ❤️ is good for this sort of “exploring an unfamiliar codebase” thing#2019-10-0313:56tatutjust eval some existing linter impl in debug mode, run the test and see the values flowing#2019-10-0313:57borkdudegreat. if you're implementing this like the other macros, then you should also get "unused bindings" in your match macro#2019-10-0313:57borkdudewhen you don't use those of course#2019-10-0313:58tatutoh yes, so if you introduce a binding in pattern but don’t use it… I’ll make a test case for that as well#2019-10-0314:05borkdude@mynomoto still good?#2019-10-0314:28mynomoto@borkdude got lost doing some fixes for a project, all good on my tests.#2019-10-0314:29borkdudealright. I'll make a release either tonight or tomorrow#2019-10-0314:31tatutthe :bindings is a map in ctx, from symbol to ?#2019-10-0314:33borkdudesymbol to map with row and col. this is typically produced by the function extract-bindings#2019-10-0314:33tatutok, I’ll look into that#2019-10-0314:34tatutbut got to go and continue later, thanks for the advice so far#2019-10-0314:34borkdudeno problem, take your time#2019-10-0315:54sammikkohi.. i'm trying to get clj-kondo working on Windows.. found this https://github.com/borkdude/clj-kondo/issues/276 .. is there anything to do to help with this or is it basically that GraalVM folks need to sort something out?#2019-10-0315:56borkdude@sammikko The issue is like this. You need to install a C++ redistributable on the system where the binary is compiled. Also you need to install from the command prompt that comes with this, so certain dlls are in scope (if I understand correctly). But these dlls are not statically linked (afaik that's not possible yet with GraalVM on Windows). So when you copy the resulting binary to a different system, then it will crash because of a missing dll.#2019-10-0315:57borkdude@sammikko There is some documentation here for building on Windows: https://github.com/borkdude/clj-kondo/blob/master/doc/build.md#windows#2019-10-0315:57borkdudeAlso there is an appveyor Windows build that runs along each commit.#2019-10-0315:58borkdudeIf you can find out a solution for Windows users, this is welcome. You might also be able to find out of you can just run the linux binary with WSL2.#2019-10-0315:59borkdudeThere is an issue on Graal for the dll stuff, but there hasn't been any news there for a while.#2019-10-0315:59sammikkoright ok.. I managed to build the exe using the instructions.. but there is no output.. also tried to copy msvcr100.dll in the same dir as exe, but no luck.. it starts but there is no output.. without --lint it does display the usage instructions tho#2019-10-0316:00sammikkook, ill try to look into it.. new to GraalVM too..#2019-10-0316:00borkdudeFWIW you can always run clj-kondo on the JVM as a lib or uberjar, but that won't be pleasant in an editor.#2019-10-0316:01sammikkoyeah.. ive tried it on osx.. its nice that its so fast.. good work 🙂#2019-10-0316:01borkdudeMight also be worth looking into GraalVM documentation around Windows. Maybe things have changed meanwhile.#2019-10-0316:01borkdudeIt would be easiest from a maintenance standpoint if WSL2 was an option.#2019-10-0316:02borkdudeNot sure about this. I'm not using Windows frequently and don't know a lot about the OS internals.#2019-10-0316:03borkdudeWhat could also work is writing an nREPL integration for clj-kondo, so you run it as a lib inside your editor REPL.#2019-10-0316:04borkdudeThis would be editor specific and up to contributors to step in.#2019-10-0316:07sammikkoright.. do you mean like starting up the clj-kondo on JVM but keeping the process alive and feeding it the "files" with some protocol ?#2019-10-0316:07borkdudeyeah#2019-10-0316:08borkdudelike cider-nrepl which is also a development-time library which lives in your REPL process#2019-10-0316:09borkdudemaybe you don't even need nREPL, haven't thought this through a lot#2019-10-0316:11sammikkowell its good to have options 🙂 ill need to do some reading on GraalVM etc.. thanks for the help!#2019-10-0320:50borkdudeI started doing clj-kondo because I wanted additional linters to joker. But in time I think it caught up with joker pretty well.#2019-10-0320:51borkdudeI have a hard time coming up with a feature that's not already in clj-kondo.#2019-10-0320:52borkdudethat's for unresolved symbols I guess#2019-10-0320:53borkdudeclj-kondo has a slightly different take on macros: you can teach it to lint custom macros as clojure.core macros. for example: lint manifold.deferred/let-flow as clojure.core/let#2019-10-0320:53borkdudeI would say: spend 20 minutes watching my talk at ClojuTRE to learn what it can do and then decide if you want to install it.#2019-10-0320:53borkdudeIt also helps you with getting rid of refer :alls.#2019-10-0320:55borkdudeI have only done one recorded talk on it, so yes 🙂#2019-10-0320:56borkdudeI explain about the difference with other linters in the talk as well#2019-10-0321:51robertfwI'm seeing a false positive being caused by clj-kondo not ignoring a defn that I have tucked away in a (comment) block. I took a look through the issues on github but didn't spot anything similar, is this a known issue? Would you like me to create an issue?#2019-10-0321:52borkdudeit's a design choice: comments often contain example code that I still want to have linted#2019-10-0321:53borkdudeif you want to ignore comments there's an option for that. but you can also choose to use uneval to comment out the defn.#2019-10-0321:55robertfwThat makes sense, though in this specific case of defning a function, it seems like the linter picking up the commented out function signature could cause other false positives in non-commented code#2019-10-0321:55borkdudetrue. personally I don't put defns in comments though, just calls (like a REPL session that could become a unit test)#2019-10-0321:56robertfwyeah, my next comment would be that I probably should be leaving this in here like this. It's an unfinished bit of code that I want to record but come back to later#2019-10-0321:57robertfwI'll just prefix the fn name with _ for now#2019-10-0321:58robertfwthanks 🙂#2019-10-0321:58borkdudeno problem#2019-10-0323:57sogaiu@sammikko fwiw, my last understanding of the situation was that one significant issue was this: https://github.com/oracle/graal/issues/1469. i'm not as confident as others regarding whether there isn't something one can do about the dll as i got some private assembly clj-kondo working to deal with the dll part. also, i think there's a chance at an ugly work-around: > using an additional program that can handle stdin / stdout communications properly to have it act as an intermediary / wrapper around Windows native-image programs generated from Clojure source. (see https://github.com/borkdude/clj-kondo/issues/276#issuecomment-517900704) the additional program would write what it receives from the invoker to disk and clj-kondo would read from disk -- after processing, clj-kondo would write the results to disk and the additional program would read them back and send them back to the invoker appropriately. the additional program could be written in rust, go, nim, etc. i got wiped out working on this before and have not seen any activity on oracle's side. i also think it would all-around be better to not be using dlls when you don't have to (see: https://github.com/oracle/graal/issues/1407#issuecomment-508688008 for details)#2019-10-0420:52sammikkogood work digging into this.. I tried your patch where in was changed to System/in and out to System/out... It seems to work different if I have .clj-kondo directory in effect with config.edn... even with the patched version, it crashes if I lint my project directory having .clj-kondo. If I try the same dir without .clj-kondo, it works and outputs the same warnings as in OSX..#2019-10-0420:56sammikkoI'm trying to "debug" it using Sysinternals Process Monitor tool.. it seems that it processes all the files, but then in the end it tries to call QueryAllInformationFile for .clj-kondo\.cache\2019.09.23-alpha-SNAPSHOT\lock resulting in BUFFER OVERFLOW#2019-10-0420:59sammikkoI didn't find any difference with msvcr100.dll, tried putting in same dir as .exe (dir is in PATH), current directory etc..#2019-10-0421:03sammikkoI'm not really familiar with windows internals... know the basics..#2019-10-0421:05sammikkoHmm.. its probably not a real buffer overflow: https://blogs.technet.microsoft.com/markrussinovich/2005/05/17/buffer-overflows/#2019-10-0421:12sammikkoit just crashes in the end, probably when trying to output something...#2019-10-0421:12sammikkohow did you get the stack trace for the crash? maybe i can try the same..#2019-10-0423:34sogaiuit may take me a bit to recreate the context due to various factors including an aging brain 🙂 if you didn't see it already, here's a repository documenting what i think is a native-image issue: https://github.com/sogaiu/constdin -- it should have instructions on ending up with a stacktrace. for the dll side of things, i don't have anything written up, but i can dig up the sxs private assembly stuff that seemed to work if you think that might help. let's see if i can attach it here -- the version of clj-kondo is from a bit back, but iirc, the important bits are the specific manifest files along with things being consistent with what's described within them.#2019-10-0423:48sogaiuok, that seemed to work...#2019-10-0500:00sogaiuif you do build your own clj-kondo.exe on windows successfully, you may find that it works better when launched from within the special console "Windows SDK 7.1 Command Prompt" setup provided by windows 7 sdk. i think we found that the built executable tended to work better on the machine / environment where it was built. i got hard-to-explain varying behavior depending on which shell the executable was launched from. the 4 shells i tested among are mentioned at the constdin repository linked above. regarding the build process, i had a lot of difficulty getting the build environment set up appropriately -- a straight-forward install of the windows 7.1 sdk just would not work. fwiw, here are my notes: https://gist.github.com/sogaiu/e079cd770051685c46ab24b6658effcf -- but may be you have this all working already 🙂#2019-10-0500:03sogaiui'm not really familiar with windows internals either. regarding "buffer overflow", i reached a similar conclusion that in this case what process monitor is telling us is not what security-conscious folks usually are concerned with.#2019-10-0404:19pezI hope to find some time to see if I can write an nrepl middleware that can start clj-kondo in-process. FWIW #2019-10-0407:32borkdude@pez nice! I enjoyed the interview with you on the ClojureScript podcast btw. good work!#2019-10-0407:42borkdudeOne alternative for Windows users could also be to use the Docker build. But I wonder if WSL/WSL2 isn't a better fit if you go that way maybe.#2019-10-0407:44pezThanks! It was recorded in May or something, so a lot has happened since. 😃 But still this linter feature that I'd really like to make it easier to use, while also letting Clojure Lint handle the actual integration of the linter and VS Code.#2019-10-0407:46pezYes, I think WSL works. But I want it to work without all that. 😃 I want it to be a no-install when using Calva. So Calva would bundle Clojure Lint, and linting would just be there, is where I want things to be. Not sure I'll be able to get there, but I'll give it a try before I stop dreaming about it.#2019-10-0407:48pezI think that it might be a usable general pattern to have nrepl start Clojure tools that the editor integrations need.#2019-10-0408:24borkdudeclj-kondo v2019.10.04-alpha https://github.com/borkdude/clj-kondo/releases/tag/v2019.10.04-alpha#2019-10-0411:21dharriganArch updated too#2019-10-0412:00Heikki HämäläinenI have a next core.match code which triggers an error in clj-kondo: (match [(-> description :status keyword)] [:SUCCEEDED] {:status :SUCCEEDED :customer_id (parse-customer-id description)} [:RUNNING] {:status :RUNNING} [(:or :FAILED :TIMED_OUT :ABORTED)] {:type :internal-server-error :message (:aws-step-function/failed error/keywords)}) The problem is (:or :FAILED :TIMED_OUT :ABORTED) which causes “error: keyword :or is called with 3 args but expects 1 or 2”. That part is core match spesific syntax. Is there way to suppress error in this case?#2019-10-0412:03tatutbtw, I’m working on a PR to support core.match#2019-10-0412:03Heikki HämäläinenYou rule!#2019-10-0412:03tatutyou could comment on that issue#2019-10-0412:04tatutI can add that as a unit test for core.match support#2019-10-0412:05Heikki HämäläinenGreat, i am putting this as a comment in the PR also for a reminder.#2019-10-0412:02borkdude@heikki.hamalainen There is: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-arity-linting-inside-a-specific-macro-call I'm in a meeting right now, so I'll be able to give more info later.#2019-10-0413:27juhoteperiIs there an option to disable if Missing else branch. warning?#2019-10-0413:32dharriganCould you use when instead?#2019-10-0413:35juhoteperiNope, existing codebase has 600 of these warnings and I don't agree that when should be used if there is only then branch and if when there are both then and else. (I think when is useful for side-effects)#2019-10-0413:37borkdude@juhoteperi yes: {:linters {:if {:level :off}}}#2019-10-0413:40juhoteperiAh thanks. Is there list of linter keys somewhere? This option isn't listed in the docs, but I guess not all linter need to be listed, if they only have level option.#2019-10-0413:41juhoteperi... yes, config doc mentions all the keys are listed in default config 🙂#2019-10-0413:42borkdudeyeah, it's in clj-kondo.impl.config.clj... could do better there, but I guess you can find it 🙂#2019-10-0413:42juhoteperiBtw, I've been collecting ideas for linters while reviewing code recently: https://gist.github.com/Deraen/85ab85a626844a4142cc5754484adae4 maybe some of these make sense?#2019-10-0414:14borkdude@juhoteperi I've just read them. Although I think they're interesting, probably not everyone will agree with these linters, which is OK, but like you are now experiencing with if, people will have to turn off the linter in existing code, etc. What you can also do is create issues for these linters and over time these could collect feedback and if there is a clear desire from the community to have specific ones, we can choose to implement them.#2019-10-0414:15borkdudeBtw, you can also choose to set :if to level :info, this way you will still get feedback (at least in Emacs). Nothing is wrong with free info maybe?#2019-10-0712:17yuhanCan I use clj-kondo's analysis info to obtain a dependency graph on the function level?#2019-10-0712:17yuhani.e. which functions reference / call which other functions#2019-10-0712:18borkdudenot yet. could be an interesting feature to add. if you can make a github issue for this with a compelling use case, that would be nice#2019-10-0712:19borkdudeI don't have any linters that use this information so I don't know how easy it will be to implement this#2019-10-0712:20borkdudebut right now it's not there#2019-10-0712:24yuhanit's more of a curiosity at the moment, I often find myself tracing the execution of a function stack through many different parts of the file and across namespaces#2019-10-0712:26yuhanIt's easy to lose track of context doing that, and thought it would be nice to output a big Graphviz file where those dependencies could be seen visually#2019-10-0712:27borkdudeI imagine the following: each var-definition lists a :depends list which has the vars it call. that's maybe not so hard to add and with this information you can build up this graph#2019-10-0712:29yuhanyes, that should be all I need :)#2019-10-0712:29borkdudehttps://github.com/borkdude/clj-kondo/issues/512#2019-10-0712:30borkdudebtw @qythium, thanks for posting the other two bugs recently. those were fixed on master. I put the links to the new binaries in the issues.#2019-10-0712:34yuhanyes I saw them but couldn't figure out how to get the linked binary recognized by flycheck, I trust they should be working and released soon though#2019-10-0712:34yuhanthanks for the quick turnaround!#2019-10-0712:35borkdudeyeah, I think end of this week maybe#2019-10-0812:44pithylessI'm seeing different linter errors on the CLI and in Spacemacs. On the CLI I'm running clj-kondo v2019.10.04-alpha; in spacemacs, I'm running (clojure :variables clojure-enable-linters 'clj-kondo ...)#2019-10-0812:44pithylessHow can I verify / debug what flycheck is actually running in emacs?#2019-10-0812:45borkdudeyou can try flycheck-compile#2019-10-0812:46pithylessah, that looks more correct! So it looks like the default runner for flycheck is incorrectly configured#2019-10-0812:51pithylessif I run flycheck-select-checker and set it to clj-kondo-clj I'm seeing the correct thing; any idea what to add to my .spacemacs to make sure it loads by default for clj/cljs/cljc/edn files?#2019-10-0812:54pithylessI just chose the nuclear option, and temporarily removed joker from the path. Looks like it was always selecting joker over clj-kondo, even though I removed joker from my .spacemacs#2019-10-0812:56pithyless@borkdude is it a known issue where emacs is apparently eating the last character of the error message?#2019-10-0812:57pithyless#2019-10-0813:01borkdudeI haven't seen this behavior before. There is spacemacs documention for kondo here: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#spacemacs And in the #spacemacs there are several kondo users.#2019-10-0813:04pithylessThanks, I've followed the wiki instructions per the develop branch; 🤷 I guess I'll look more into it later.#2019-10-0813:10borkdudeThe people in #spacemacs have been very helpful to these kinds of issues before.#2019-10-0815:24Marc O'MorainRe this issue: https://github.com/borkdude/clj-kondo/issues/514 The motivating examples are parsing this:
{) ; => Unmatched delimiter: ) [at line 1, column 2]
and this:
[ ; => Unexpected EOF. [at line 1, column 2]
#2019-10-0815:26borkdudeas discussed: maybe it's an idea to keep a reference to last opened delimiter. when Unmatched or Unexpected happened, we can include the row and col of that last opened delimiter (if there is one).#2019-10-0815:26Marc O'MorainWhat should the error messages actually be in this case? For the second example, if I forget to close a ) in a function on line 5 of a 300 line file, the error is currently that there was an unexpected EOF on line 300, not that was an unclosed paren on line 5. So there error message is 295 lines away from the error.#2019-10-0815:27borkdudeIn the first case I'd say: an extra unmatched delimiter for the opening {#2019-10-0815:27borkdudeIn the second case: does it work to also report the last opened delimiter position?#2019-10-0815:28borkdude( <-so this one foo (.....) (....)#2019-10-0815:29borkdudeso as soon we encounter a closing delimiter, we forget about the last opened one#2019-10-0815:29borkdudebut as soon as we encounter one of the above errors, we also report the last opened delimiter that wasn't closed yet#2019-10-0911:39fmnoiseis there any way of marking clj-kondo aware of bindings created by macros similar to let?#2019-10-0911:44delaguardoYou can configure linter to read custom macro as a build-in macro (let as example) https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#lint-a-custom-macro-like-a-built-in-macro#2019-10-0911:48fmnoisethanks @delaguardo!#2019-10-0912:27fmnoiseshould it work with flycheck-clj-kondo?#2019-10-0912:27fmnoisecause seems it doesn't#2019-10-0914:19malch@fmnoise It should, try restarting Emacs#2019-10-0914:25borkdude@fmnoise that config goes into .clj-kondo/config.edn typically#2019-10-0914:42borkdudeit should work with flycheck-clj-kondo like on the command line.#2019-10-0915:05fmnoiseah, I see, restarted emacs but no luck yet#2019-10-0915:06fmnoiseoh, sorry, that was joker compaining#2019-10-0915:06fmnoiseclj-kondo is fine about that#2019-10-0915:06fmnoisethanks guys#2019-10-0915:40borkdudewhat can also help next time is executing flycheck-compile#2019-10-1108:57borkdude@tatut https://github.com/borkdude/clj-kondo/issues/259#issuecomment-540979321#2019-10-1108:59borkdudeI want to include this is the next release. Maybe later today.#2019-10-1108:59tatut:thumbsup: nice
#2019-10-1114:14borkdudeclj-kondo v2019.10.11-alpha: mostly minor bugfixes and enhancements https://github.com/borkdude/clj-kondo/releases/tag/v2019.10.11-alpha#2019-10-1114:18dharriganarch updated#2019-10-1114:36borkdudeThanks! That's quick.#2019-10-1114:37dharrigan🙂#2019-10-1114:37dharriganNo guarantees that next time will be the same 🙂#2019-10-1410:03Hannu Hartikainen(ns foo (:require ["bar" :as Bar])) (Bar.) gives a warning for unused namespace. That’s a normal use case with shadow-cljs when a js library has module.exports = Bar.#2019-10-1410:03Hannu HartikainenI’d like to provide a fix but am not sure where to start.#2019-10-1410:06borkdudeis this also normal when using plain CLJS?#2019-10-1410:06Hannu HartikainenIn fact it seems to me like there’s something off with constructor calls…#2019-10-1410:06Hannu HartikainenI think so, but I only work with shadow-cljs right now.#2019-10-1410:07borkdudeI think there was already a fix for this when using Bar as a value recently. But interop is pretty much ignored by clj-kondo, so the fix might not be straight forward.#2019-10-1410:07borkdudeFeel free to post an issue so I can think about it more. I'd be happy to point you in the right direction if you want to do a PR. Please post that in the message as well, if you're interested in doing one.#2019-10-1410:09borkdudeI think you can avoid the false positive right now, by just having something like (comment Bar) in your code 😜#2019-10-1410:11borkdudethis was the fix when using Bar as a value: https://github.com/borkdude/clj-kondo/commit/a45565de713cc5c510640c247d2f013777eaff54#2019-10-1410:12borkdudein fact it might be easy to hack it in in that place, by just stripping the last dot#2019-10-1410:12borkdude^ @hannu.hartikainen#2019-10-1410:13Hannu HartikainenOk. I’m reading CLJS docs now to see if this is a shadow-cljs extension and I’m starting to think it is. Still interested in a fix?#2019-10-1410:15Hannu Hartikainen> As discussed on Slack: it would be nice to only have this behavior if the user requires the namespace using a string. yes, that would be a good way to do both of these#2019-10-1410:15borkdudeI remember this feature not being documented well in CLJS but as a value it still worked#2019-10-1410:16borkdudeThe string require is already in there as a later commit #2019-10-1410:16Hannu HartikainenYep, I’ll read it later and make sure this works the same way. Thanks!#2019-10-1412:55martinklepschHas there been a conversation around Rum + clj-kondo? Rum’s macros trip up some of the analysis and I’m not sure it’s as easy as saying “they’re like defn” because they can take mixins etc#2019-10-1508:26borkdude@martinklepsch I looked at the README and found this snippet:
(ns foo
  (:require [rum.core :as rum]))

(rum/defcs stateful < (rum/local 0 ::key)
  [state label]
  (let [local-atom (::key state)]
    [:div { :on-click (fn [_] (swap! local-atom inc)) }
     label ": " @local-atom]))

(rum/mount (stateful "Click count") js/document.body)
I think I would config that as:
{:lint-as {rum.core/defcs clojure.core/def}
 :linters {:unresolved-symbol {:exclude [(rum.core/defcs)]}}}
#2019-10-1508:27borkdudeso you will lint the macro as def because it defs a var, but you will ignore all unresolved symbols in the call to it#2019-10-1509:01borkdudecreated a project board for clj-kondo here: https://github.com/borkdude/clj-kondo/projects/1#2019-10-1509:04martinklepschI see, thanks @borkdude! would it be in scope for clj-kondo to support custom macros like defc and friends more completely?#2019-10-1509:05borkdudecould implement support for it. is rum considered a widely used lib and does the author plan to support it long term? (I noticed he recently removed the patreon link for it)#2019-10-1509:16martinklepschI would consider it among the more popular libs for sure. I think there’s not much active development but people use it and its stable.#2019-10-1509:17borkdudealright. could you make an issue for it and describe some variations of macros that you think should be supported?#2019-10-1509:18borkdudeit's not that hard probably. clj-kondo also supports other defn like macros like schema.core/defn#2019-10-1509:44martinklepsch@borkdude logged an issue: https://github.com/borkdude/clj-kondo/issues/536 thanks for considering it 🙂#2019-10-1615:28Hannu HartikainenI might have an idea for automatic diffs for performance test output. I guess you could save the output in circleci cache with a key that includes commit hash. Then get master results from cache (or compile and run if it's missing) and report differences using whatever circleci has available.#2019-10-1615:34borkdudeyeah, that would work. or use some artifact API#2019-10-1615:37Marc O'Morain#2019-10-1615:38Marc O'MorainWe have no more warnings in clj-kondo in the CircleCI monolith 🎉#2019-10-1615:40borkdude@marc-omorain congrats.#2019-10-1615:41Marc O'Morainwe have a lot of :info left 😂#2019-10-1615:41borkdude@marc-omorain Hannu and I were discussing this feature: https://github.com/borkdude/clj-kondo/pull/537#issuecomment-542607125 It would be cool if we could use CircleCI to generate this diff (branch vs master) and show it in a PR#2019-10-1615:41Marc O'Morain
:private-call {:level :info}
:unused-binding {:level :info}
:not-empty? {:level :info}
#2019-10-1615:41borkdudethat's fine I guess#2019-10-1615:42borkdudeyou can use clj-kondo how you want, that's why it's configurable 🙂#2019-10-1615:43Marc O'MorainThe private-calls are complicated. We use for stubbing, and stubbing private vars produces the private call warning.#2019-10-1615:43Marc O'MorainWe are hoping to filter that warning to be :error in src/ and ignored in test/#2019-10-1615:46borkdudeyou could lint src and test with different configs#2019-10-2110:52borkdude@filipematossilva updated his npm package to fall back on the jar if the native version isn't supported.#2019-10-2110:53Filipe Silva👋#2019-10-2110:53borkdudeThis means that when you install the NPM package on Windows and install the clojure-lint plugin in VSCode, linting should work on save now#2019-10-2110:53Filipe Silvayou should be able to do it globally even, via npx clj-kondo --lint src/#2019-10-2110:53borkdudeusing a JVM, so feedback might not be as fast with the native version, but it should work I guess!#2019-10-2110:53Filipe Silva(if you don't want a local package)#2019-10-2111:03Filipe Silvawas just testing if the extension just worked if I installed the package globally#2019-10-2111:03Filipe SilvaI'm on windows and did npm i -g clj-kondo#2019-10-2111:03Filipe Silvathe binary works#2019-10-2111:03Filipe Silva
$ clj-kondo
clj-kondo v2019.10.11-alpha

Usage: [ --help ] [ --version ] [ --lint <files> ] [ --lang (clj|cljs) ] [ --cache [ true | false ] ] [ --cache-dir <dir> ] [ --config <config> ]

Options:

  --lint: a file can either be a normal file, directory or classpath. In the
    case of a directory or classpath, only .clj, .cljs and .cljc will be
    processed. Use - as filename for reading from stdin.

  --lang: if lang cannot be derived from the file extension this option will be
    used.

  --cache-dir: when this option is provided, the cache will be resolved to this
    directory. If --cache is false, this option will be ignored.

  --cache: if false, won't use cache. Otherwise, will try to resolve cache
  using `--cache-dir`. If `--cache-dir` is not set, cache is resolved using the
  nearest `.clj-kondo` directory in the current and parent directories.

  --config: config may be a file or an EDN expression. See
    .
#2019-10-2111:03Filipe Silvabut the extension says#2019-10-2111:04Filipe Silva
Clojure Lint extension loaded.
Please report any issues to 
clj-kondo was not found on the path. Please install it following the instructions
located here: "
#2019-10-2111:04borkdude^ @marc-omorain#2019-10-2111:05Marc O'Morain@filipematossilva did you re-open VSCode after putting clj-kondo on the %PATH%?#2019-10-2111:05Marc O'Morainwhat do you see when you run clj-kondo from a CMD.EXE terminal?#2019-10-2111:05Filipe Silvayes, I restarted vscode, just tried restarting again#2019-10-2111:06Filipe Silvaon cmd I see this#2019-10-2111:06Filipe Silva
Microsoft Windows [Version 10.0.18362.418]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Users\kamik>clj-kondo
clj-kondo v2019.10.11-alpha

Usage: [ --help ] [ --version ] [ --lint <files> ] [ --lang (clj|cljs) ] [ --cache [ true | false ] ] [ --cache-dir <dir> ] [ --config <config> ]

Options:

  --lint: a file can either be a normal file, directory or classpath. In the
    case of a directory or classpath, only .clj, .cljs and .cljc will be
    processed. Use - as filename for reading from stdin.

  --lang: if lang cannot be derived from the file extension this option will be
    used.

  --cache-dir: when this option is provided, the cache will be resolved to this
    directory. If --cache is false, this option will be ignored.

  --cache: if false, won't use cache. Otherwise, will try to resolve cache
  using `--cache-dir`. If `--cache-dir` is not set, cache is resolved using the
  nearest `.clj-kondo` directory in the current and parent directories.

  --config: config may be a file or an EDN expression. See
    .


C:\Users\kamik>
#2019-10-2111:07Filipe SilvaI suspect this is due to npm creating both clj-kondo and clj-kondo.cmd#2019-10-2111:07Filipe Silvacmd.exe will actually use the latter (I think?)#2019-10-2111:08Filipe Silva
C:\Users\kamik>where clj-kondo
C:\Program Files\nodejs\clj-kondo
C:\Program Files\nodejs\clj-kondo.cmd
#2019-10-2111:21Marc O'MorainThe error must be here: https://github.com/marcomorain/clojure-lint/blob/cdd49c92365f4e28fd4e9baed7c6f0c65e93dd16/src/extension.ts#L47-L73#2019-10-2111:22Marc O'Morainhttps://nodejs.org/api/child_process.html#child_process_child_process_execfile_file_args_options_callback#2019-10-2111:24Marc O'Morain@filipematossilva can you rename clj-kondo to clj-kondo.exe please and see if that affects the issue?#2019-10-2111:25Marc O'MorainThat might be the issue.#2019-10-2111:25Marc O'MorainWindows process launching is “interesting”#2019-10-2111:27Filipe SilvaI can't do that, because just renaming it doesn't make it a real exe#2019-10-2111:27Filipe Silva
C:\Users\kamik>clj-kondo
This version of C:\Program Files\nodejs\clj-kondo.exe is not compatible with the version of Windows you're running. Check your computer's system information and then contact the software publisher.
#2019-10-2111:28Marc O'Morainoh, what file type is it?#2019-10-2111:29Filipe Silvait's a .cmd script#2019-10-2111:29borkdudemaybe making the script command configurable works?#2019-10-2111:29Marc O'MorainThat’s going to be the issue. I’m calling execFile which is not using a shell, it’s trying to execute a binary directly I think.#2019-10-2111:29borkdudeoh#2019-10-2111:29Filipe Silvathat part is out of my hands though, it's how npm/yarn do things#2019-10-2111:30Filipe Silvait'll create those binaries automatically#2019-10-2111:30Marc O'MorainThis should be straightforward to fix in clojure-lint. But I don’t know how 😄#2019-10-2111:31Marc O'MorainI’m on a mac right now, I might boot Windows later today or tomorrow and have a look at it.#2019-10-2111:31Marc O'MorainPRs are always welcome thought!#2019-10-2111:31borkdudeDifferent issue: to make linting on Windows speedier this could also work: https://github.com/borkdude/clj-kondo/issues/541#2019-10-2111:37Filipe Silva@borkdude I imagine that'd require some extra process communication that doesn't yet exist, right?#2019-10-2111:39Filipe Silva@marc-omorain I think it's enough to also try running clj-kondo.cmd instead of clj-kondo on windows... is there an easy way for me to test that? e.g. whats the global extension dir, I can try changing it there#2019-10-2111:39borkdudethe way I imagine it is you run java -jar clj-kondo.jar --server 1337 once in your project dir (so one server per project). This startup could be automated by checking if it already runs and if not start it. and then there will be a clj-kondo-client which will support exactly the same command line args as clj-kondo, but acts as a proxy between the editor and the jvm process#2019-10-2111:41borkdudemaybe the client can just be named clj-kondo which will start the server in the background if it's not already running, to make things more align with the binary#2019-10-2111:41borkdudepreferably that client will be very very fast and supported on all platforms, so maybe Go is a good choice there#2019-10-2111:42borkdudehey, this looks a lot like what @dave is doing with Alda 🙂#2019-10-2112:29daveYep, that sounds almost exactly what I'm doing! Actually, Alda v1 (the current major release version) has a client written in Java. Alda v2 has a Go client, but I'm also doing something different there where I'm moving most of the logic into the client.#2019-10-2112:30borkdudeI might look at your go client code and how you distribute it. Never done any Go#2019-10-2112:30daveWhen you write the client in a JVM language, one benefit is that you can package it into the same uberjar as the server, and just have a single executable that can run in either client or server mode. That simplifies releases#2019-10-2112:30borkdudeyeah, but I'm trying to workaround JVM startup time#2019-10-2112:32borkdudeit's just that GraalVM doesn't work that well yet on Windows#2019-10-2112:32borkdudeso a thin Go client + JVM server process might work#2019-10-2112:32borkdudeI was thinking the Go client can start the JVM server process when it wasn't started yet#2019-10-2112:33borkdudesomething for the hammock#2019-10-2300:01daveThat sounds like a promising approach!#2019-10-2111:46Filipe Silva@marc-omorain yeap, using clj-kondo.cmd in the extension on windows works!#2019-10-2111:46Filipe Silva#2019-10-2111:47borkdude😄#2019-10-2111:53Filipe Silva@marc-omorain here's a PR https://github.com/marcomorain/clojure-lint/pull/10#2019-10-2111:58borkdudeas part of that PR you could maybe also check if clj-kondo was installed via npm or have a fallback, if clj-kondo does not exist, then try clj-kondo.cmd? @filipematossilva#2019-10-2112:01Filipe Silvato do that in a cross platform way would require a somewhat more involved approach#2019-10-2112:02Filipe Silvajust trying to run the commands isn't a great approach, because that can take a while#2019-10-2112:02Filipe Silvaso it would be an overhead that might not be reasonable depending on how even these are ran#2019-10-2112:03Filipe Silvasomething like shelljs could be used to provide a cross platform which command, and then we could do which clj-kondo#2019-10-2112:04Filipe Silvawhich on windows will return the .cmd (in the npm case)#2019-10-2112:04Filipe Silvaand whatever else is actually ran by the system in the non-npm case#2019-10-2112:04borkdudeI wasn't suggesting running them, just checking if they exist on the path?#2019-10-2112:05borkdudenot sure what you can and cannot do in visual studio code out of the box without installing extra stuff#2019-10-2112:05Filipe Silvahmmm I'm not that familiar with the vscode builtins myself...#2019-10-2112:05borkdudemaybe @marc-omorain knows...#2019-10-2112:06Filipe Silvawhich in shelljs would check the path as you describe, but checking it without shelljs would need some finicky cross platform coding#2019-10-2112:06borkdudehttps://stackoverflow.com/questions/58451856/vscode-api-check-if-path-exists#2019-10-2112:06borkdudebut that might not work for the PATH path#2019-10-2112:06borkdudenot sure#2019-10-2112:06Filipe Silvano, it doesn't#2019-10-2112:07Filipe Silvathat's just checking if a particular absolute path exists#2019-10-2112:07Filipe Silvabut it might be anywhere in the path really#2019-10-2112:07borkdudeyeah ok#2019-10-2112:14borkdudeI don't know how shelljs performs under Windows. The check has to be fast#2019-10-2112:17borkdudecan't see anything here why it would be slow: https://github.com/shelljs/shelljs/blob/master/src/which.js (just skimmed it)#2019-10-2112:19borkdudeif we're going to do something more sophisticated, maybe it's good to populate the command variable outside the lint function, only at startup?#2019-10-2112:20borkdudeI'll leave that to you @marc-omorain and @filipematossilva to decide 🙂#2019-10-2112:20Marc O'MorainI’m working on a patch for shelljs now#2019-10-2112:21pezShouldn't the extension just bundle the npm package?#2019-10-2112:24Marc O'Morainhttps://github.com/marcomorain/clojure-lint/pull/11 @filipematossilva could you take a look please? 👀#2019-10-2112:28borkdude@marc-omorain this which command is now executes every time you lint a file. I don't know if this is milliseconds, then it probably doesn't matter, but maybe it makes sense to lift it outside the lint function.#2019-10-2112:28Marc O'MorainYeah, I’ve been thinking about that. Users would have to restart VSCode after installing clj-kondo in that case.#2019-10-2112:29borkdudehmm#2019-10-2112:29Marc O'MorainBut that’s probably going to be the case on Windows anyway?#2019-10-2112:29borkdudenot sure, yeah, tradeoff#2019-10-2112:29Marc O'MorainI could cache the positive result though.#2019-10-2112:31borkdudeRight. I think optimizing for speed for most common usage is maybe a sane thing to do#2019-10-2112:40Filipe Silvasorry for the delay, was AFK for a while#2019-10-2112:40Filipe Silvayeah I don't know how long which takes, but it might take a while depending on your path#2019-10-2112:40Filipe Silvaand it's really just something that needs to happen once#2019-10-2112:41Filipe Silvaso it makes sense to lift it out#2019-10-2112:42Filipe SilvaI think it makes sense to bundle clj-kondo as a npm dep as well, but that makes it a bit heavier and since there's no override, locks the user to a certain version#2019-10-2112:43Filipe Silvaother npm based extensions like tslint and the like usually do a priority list with override > local > bundle#2019-10-2112:43borkdudeyeah, I would prefer letting users decide how to install it#2019-10-2112:43borkdudeand if it's not installed then use the included package#2019-10-2112:44borkdudeif that's possible (so what Filipe said)#2019-10-2113:03Marc O'Morainagreed#2019-10-2114:05borkdudeMaybe implementing some diagnostics in the LSP works for most editors as well. https://github.com/Microsoft/vscode-extension-samples/tree/master/lsp-sample#2019-10-2114:05borkdudeSo you can start kondo as an LSP server and then lint using existing LSP tools?#2019-10-2114:11Filipe SilvaI imagine @pez has a LSP server on Calva, since it offer completion#2019-10-2114:17pezNo LSP yet. Calva's completion is nrepl based. #2019-10-2114:20pezI want to experiment with starting a clj-kondo daemon on the repl server. And provide an API for the linter extension. #2019-10-2114:21Marc O'Morainhttps://elm-lang.org/news/the-syntax-cliff#2019-10-2114:21Marc O'MorainSome error messages examples ^#2019-10-2114:21Filipe Silvaelm really went the extra mile with error messages#2019-10-2114:22Marc O'Morain#2019-10-2114:22borkdude@pez That's kinda the same as https://github.com/borkdude/clj-kondo/issues/541 so maybe we can collaborate. But maybe if this server mode supports LSP it makes it easier for existing tooling to use as well#2019-10-2114:23borkdudewell maybe it's not the same. if you have nREPL you have a running JVM so that's the mechanism to avoid startup#2019-10-2114:24borkdudeso there isn't anything extra needed for that#2019-10-2114:24pezYes, that's the idea. #2019-10-2114:24borkdudeinteresting. I'll let this sit on the hammock some more and see how your approach works out#2019-10-2114:27pezRead that issue now. As for a node version. Could clj-kondo be made a cljc project?#2019-10-2114:28borkdudeI think it could, but this would mean me taking a sabbatical of one - three months, maybe a Clojurists Together sponsorship. Not sure when I'll be able to do that amount of work#2019-10-2120:40danielcomptonOur next funding round is coming up very soon, we'd love to have you apply!#2019-10-2120:53borkdudeMe too. I'm sure I will one day, but not this time 🙂#2019-10-2208:37borkdude> We don't have an exact date for when this is going to be ready, but it is coming soon. For members interested in learning more, please reach out and we're happy to give you a preview. I'm interested 😉#2019-10-2114:29borkdudeMost work is porting the rewrite-clj parser bits to CLJS (which is already done in @lee's port of rewrite-clj, but we can't use that off the shelf since there are changes from the original for good reasons).#2019-10-2114:30borkdudeLong term it's something I'm open to, but not something that will be there soon, unless someone else is willing to do this.#2019-10-2114:30borkdudeIt would be cool to be able to invoke clj-kondo in a browser playground all client side#2019-10-2118:53borkdudeBefore I send this out to the tweetosphere, can you confirm if this works now @filipematossilva and @marc-omorain? 🙂
Clj-kondo @ NPM (by @filipematossilv) now falls back to .jar file if native isn't there. If you use Windows:

- npm install -g clj-kondo
- in VSCode: install clojure-lint (by @atmarc) 
- edit Clojure file, hit save and enjoy feedback!

Report findings at:

#2019-10-2118:53borkdude(Still not sure if running a JVM on save feels that great, maybe it should be configured as a command, or that's already possible?)#2019-10-2119:13pezIs there a reason why the Clojure lint extension does not include the clj-kondo npm module?#2019-10-2119:14Filipe SilvaI think it should work after Marc does a release#2019-10-2119:14Filipe Silvabut earlier today there was no release I could test#2019-10-2119:19Filipe Silvato be fair the npm distro of clj-kondo exists as of a couple of days, this is all very new#2019-10-2119:19Filipe Silvamy suggestion to bundling is https://clojurians.slack.com/archives/CHY97NXE2/p1571661783095100#2019-10-2119:22pez@borkdude: I’ve started to think there is not all that much to gain from starting clj-kondo through nREPL, if you implement that server mode. Then an extension like Clojure lint can bundle the npm package, run clj-kondo in server mode and hand it linting tasks. The only difference would be a JVM process less, but that is not too much of a bother, is it?#2019-10-2119:23Filipe Silvaversion control is a concern, if you always use the bundled version you can't control it (hence the local bit)#2019-10-2119:24Filipe Silva(this is unrelated to server concerns/benefits)#2019-10-2119:24borkdudeI agree with Filipe: there should always be a way for users to override the bundled one with their own package manager#2019-10-2119:24pez@filipematossilva, not sure what is meant with no overrides, but if I understand it… nothing stops Clojure lint from offering the user to specify if the bundled version should be used or something else.#2019-10-2119:25Filipe Silvayes there's nothing stopping it, it's just functionality that would need to be developed#2019-10-2119:25pezyeah, but we are develpers, after all. 😃#2019-10-2119:25borkdude@pez I'm investigating LSP mode. That could work for all kinds of editor plugins. But it might take a while before I have this, while including it in nREPL might be more or less trivial (don't know)#2019-10-2119:26pezLSP mode would be cool.#2019-10-2119:26Filipe SilvaA good example is typescript: you don't always want the latest version, and you don't want to manually config each project you open. VSCode automatically picks up your local version if you have it, but also lets you specify a version on disk to use (e.g. a global you want). But it also bundles its own version that it uses for many things, like auto-fixes and code-intel for JS.#2019-10-2119:27pezYeah, that’s nice. Clojure lint could do the same.#2019-10-2119:27borkdudeI have an lsp branch and it does this right now:
$ lein clj-kondo --server
Exception in thread "main" java.lang.ClassCastException: org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor$1 cannot be cast to java.lang.Number, compiling:(/private/var/folders/2m/h3cvrr1x4296p315vbk7m32c0000gp/T/form-init8209597301223963447.clj:1:125)
Just hacked on it for half an hour 😉
#2019-10-2119:32Filipe Silvabtw @pez @borkdude, have you looked into suggested fixes?#2019-10-2119:33Filipe Silvathat's something really nice in VSCode#2019-10-2119:33Filipe Silvait's mostly code transforms#2019-10-2119:33Filipe Silvasome of them come from the tslint I believe, and some come from VSCode TS support#2019-10-2119:34Filipe Silvait's stuff like import organizing, correction for common mistakes, and auto-imports#2019-10-2119:34Filipe Silvathe latter is ostensibly the most useful imho#2019-10-2119:35Filipe Silvayou start writing a var name that doesn't exist in the current module, you get a red squiggly that tells you the ref is bad#2019-10-2119:35Filipe Silvabut it also tells you something like "Did you mean to import X?"#2019-10-2119:35Filipe Silvathen it does it for you#2019-10-2119:36Filipe SilvaI think it's LSP powered but am not sure#2019-10-2119:37pezIt’s probably LSP powered.#2019-10-2119:49borkdude@filipematossilva Implementing fixes is not in scope for clj-kondo, there are just too many things to do already 🙂#2019-10-2119:51borkdudeHmm, there is https://github.com/snoe/clojure-lsp which does a lot of refactorings. Maybe it could adopt clj-kondo as a library, since it also mentions joker#2019-10-2119:51borkdudeThat might work well, since clojure-lsp already does transformations and it can just pick up on the information the clj-kondo provides#2019-10-2119:52borkdudeThat would also be a solution in Windows#2019-10-2119:52borkdudeand it would save clj-kondo figuring out all the lsp stuff#2019-10-2119:53borkdude@dave I see you're a committer there. ^#2019-10-2119:53Filipe Silva@snoe seems to be on slack#2019-10-2119:55Filipe Silva(@snoe is the owner of clojure-lsp, we were talking about clj-kondo LSP support)#2019-10-2119:55borkdudeHi @snoe!#2019-10-2119:57Filipe Silvabtw I see there's a VSCode POC on https://github.com/snoe/clojure-lsp/tree/master/client-vscode, was it ever released as an extension?#2019-10-2120:02snoehiya! it wasn't released, I would like someone who uses vscode to take it over.#2019-10-2120:04Filipe SilvaHmmm I use VSCode almost exclusively. How can I help?#2019-10-2120:08Filipe Silvaalthough to be fair this sounds very complimentary to @pez’s vscode Calva extension#2019-10-2120:08Filipe Silvamaybe it could be incorporate somehow? or maybe made optional#2019-10-2120:21pezWe have been experimenting a little with it and we love it. However, we haven’t had the time to ponder if we should incorporate it. Maybe we should, and maybe we should even take it over… But that is something I need to think quite a bit about before deciding. We might be spreading ourselves thin if we do that.#2019-10-2120:42snoe@filipematossilva I'm not sure, I would like it so vscode users can be sure they have the latest clojure-lsp release. If that can be done as a separate repo that downloads from github releases that would be nice.. If it's most usable inside the repo that's fine and I can take prs and work to getting the maintainer commit access.#2019-10-2120:52Filipe Silva@snoe I just did that for clj-kondo, by distributing the binaries via npm#2019-10-2120:52Filipe Silvahttps://github.com/filipesilva/clj-kondo#2019-10-2120:53Filipe Silvait downloads binaries according to platform, clj-kondo distributes native binaries for linux and osx, and a jar for windows#2019-10-2120:54Filipe Silvawould it help if I did something similar for clojure-lsp?#2019-10-2120:55Filipe Silvafrom the releases page it's not clear to me what platform the binary is for, I guess linux/osx?#2019-10-2121:10snoeit's wrapping a jre - there's some difficulties with windows but yeah, whatever works would be great#2019-10-2121:11snoesorry wrapping a call to a jre#2019-10-2120:03borkdude@snoe I notice both our projects (clojure-lsp and clj-kondo) are maintaining their own fork of rewrite-clj now 🙂#2019-10-2120:04borkdudeI'm considering LSP support for clj-kondo for people who can't run the binary (most specifically Windows users)#2019-10-2120:05borkdudeBut since you're basically already doing LSP for Clojure, maybe it could be interesting to see if including clj-kondo as a linting library in clojure-lsp works well#2019-10-2120:07borkdudeJust an idea, since you already mentioned joker in your README#2019-10-2120:10snoeI would love to do this. My difficulty is really how to avoid parsing files once for lsp and once for kondo. Maybe I shouldn't worry about it cause the kondo linting would be very nice for lsp users.#2019-10-2120:11borkdudeOr you could ride along on the vendorized version of rewrite-clj in clj-kondo#2019-10-2120:11borkdudeIf you would include joker then the files would also be parsed twice btw#2019-10-2120:12snoeRight joker is file specific though, I think kondo crawls the project?#2019-10-2120:12borkdudenot really, it just lints whatever you tell it to#2019-10-2120:12borkdudeThis is the Clojure API: https://cljdoc.org/d/clj-kondo/clj-kondo/2019.10.11-alpha/api/clj-kondo.core#2019-10-2120:13borkdudeI'm not sure what the workflow is with LSP. Is a server started per project, file or editor instance?#2019-10-2120:14borkdudeclj-kondo kinda assumes that your working dir is the project directory#2019-10-2120:15snoeIt depends on the client, but clojure-lsp assumes one is started per project.#2019-10-2120:15borkdudethe benefit of linting your entire project/classpath is that it learns about the arities of functions in all namespaces, so you will have extra warnings, but it's completely optional#2019-10-2120:15borkdudeoh that's in line with how clj-kondo works then, nice#2019-10-2120:17borkdudetypically users put a .clj-kondo directory in the root of their project. then clj-kondo will save information to the .clj-kondo/.cache directory every time you lint a file (= typically when you edit a file)#2019-10-2120:17borkdudethat's how it remembers arities/etc. of previously edited namespaces#2019-10-2121:32borkdudescratch the idea of using the vendored clj-kondo parser btw, that's a bad idea and you won't be able to actually generate the original output again#2019-10-2120:40danielcomptonOur next funding round is coming up very soon, we'd love to have you apply!#2019-10-2205:33whiloI have just played around with the current type checking. Nice work. How can I define the type of my own functions?#2019-10-2207:21borkdudehey @whilo. that's documented here: https://github.com/borkdude/clj-kondo/blob/master/doc/types.md please note that this format is WIP and might change (although I hope not too much and I will document changes)#2019-10-2220:23whiloWhat would be necessary to derive these type definitions from spec?#2019-10-2220:35whiloI think one problem that core.typed had was that too few people wrote type definitions. A possibly very restricted subset of spec would be better than having your own type definitions. A problem of this approach would be that it can limit the use of spec for users. The restricted definitions could be an overlay that automatically tries to use spec when there is no restricted type definition available. But you are more familiar with the details of spec, I assume I am idealizing a bit.#2019-10-2220:37whiloIf this is unclear I can rephrase it.#2019-10-2221:01borkdudeOne problem with spec is that you cannot express a direct relation of the arity of your function and the return type.#2019-10-2221:01borkdudeAnother problem is: spec is alpha, it might change. I'm not going to build on quicksand 🙂#2019-10-2221:01borkdudeAlso, the current format is mostly designed for one pass, speed#2019-10-2221:02borkdudeThere could be other more convenient formats that translate to this format of course#2019-10-2221:03borkdudeAnother issue with spec is that there can be many indirections, specs pointing at other specs in other files. Hard to lint. Not impossible, but hard.#2019-10-2221:04borkdudeSpec is not designed as a language for expressing types, but more like a runtime contract system.#2019-10-2221:05borkdudeSpec is also not serialisable. I want something that people can put in an .edn file.#2019-10-2221:06borkdudeI have tried spec in the beginning btw, but these were some of the issues I had with it#2019-10-2221:07borkdude^ @whilo#2019-10-2221:15whiloOk, I see. It is a bit peculiar that the development of spec takes so long and feels a bit intransparent.#2019-10-2221:17whiloThese issues make sense, could you talk to some spec developers about them?#2019-10-2221:20borkdudeyeah, I have talked to Alex about it. He mentioned they were going to maybe introduce a defn-like macro for specs. Once that's out and out of alpha, I'm keen on supporting that#2019-10-2221:27whiloI think it is not strictly necessary for a type system not to contain functions, which would be required to put into an edn file. Having a validating function definition could be meaningful if one can analyze its source as well.#2019-10-2208:46borkdudeGot a hello world version of clj-kondo.lsp working 🙂 Adding the real diagnostics can't be that hard now the plumbing is more or less there#2019-10-2210:25borkdude@filipematossilva I'll probably publish the server part of clj-kondo.lsp using this: https://github.com/BrunoBonacci/lein-binplus It wraps an uberjar in a executable-like thing that works on any platform. Maybe that can also be used for the normal clj-kondo on Windows#2019-10-2213:04Filipe Silvaah I guess that's what clojure-lsp does?#2019-10-2213:04Filipe Silvayes that would work#2019-10-2213:04Filipe SilvaI guess it ends up being the exact same thing as I'm doing, just one jar less#2019-10-2213:05Filipe Silvabut I image your native images for osx/linux are still faster#2019-10-2213:05borkdudeyes, that wrapped jar executable would only be for Windows#2019-10-2213:05borkdudeuntil GraalVM sorts things out for Windows#2019-10-2213:06Filipe SilvaFWIW windows user numbers are quite high, at least on the npm ecosystem#2019-10-2213:06Filipe Silva~50% of Angular users are on Windows for instance#2019-10-2213:07borkdudeI'm not downplaying the importance of Windows, I just don't know anything better right now 🙂#2019-10-2213:08borkdudeI think clj-kondo.lsp will help these users. The startup time for command line usage isn't much of an issue. It's the editor feedback that should be fast.#2019-10-2213:08Filipe Silvayes I know, just wanted to give perspective#2019-10-2213:08Filipe SilvaI think there's a common perspective that windows users are a minority, but the reality ends up being different#2019-10-2213:09borkdudeI'd like to see Windows % in the next Clojure Survey#2019-10-2213:19Filipe Silvathat's a tricky one#2019-10-2213:19Filipe Silvaalthough it would be accurate for survey respondents, they might not accurately represent the population#2019-10-2213:20Filipe Silvadoes maven provide download stats per OS?#2019-10-2213:21Filipe Silvathat might be a more accurate, if it can filter out CI machines#2019-10-2213:21borkdudeclj-kondo is published to clojars. not sure if it has those stats#2019-10-2216:12borkdude@snoe Do you have Windows users of clojure-lsp? I just tried the lein bin plugin you're using with one of my own jars and it didn't run for me in a Windows VM#2019-10-2216:19snoe@borkdude there's been a couple, and I have a number of open issues around it, kinda hoping someone champions it cause it's difficult for me to get a handle on.#2019-10-2216:21borkdudeI'm experimenting with bundling a .jar file in a VSCode extension. I first tried the lein bin approach, but I got a 32-bit error in a Windows VM. java -jar does work#2019-10-2216:23snoeyeah, there's a few other older school things like jar2exe. I wanted to get ci running on azul to be able tot test them all#2019-10-2216:23borkdudehttps://github.com/borkdude/clj-kondo.lsp/blob/cbed6cca096db346e9ee2e1951e680d688d52fbf/vscode-extension/src/extension.ts#L25#2019-10-2218:15dominicmIs anyone using clj-kondo with Github actions and has that process documented?#2019-10-2219:20Filipe Silva@snoe I can help you get github actions working#2019-10-2219:20Filipe Silvait has windows CI too#2019-10-2219:21Filipe Silvahttps://github.com/filipesilva/clj-kondo is running on github actions to test#2019-10-2219:21snoeoh perfect#2019-10-2219:21Filipe Silva@dominicm do you mean just running clj-kondo on github actions for CI, or a github action that runs clj-kondo on your code?#2019-10-2219:22borkdudeI think he means the latter#2019-10-2219:23Filipe Silvathat I have never done#2019-10-2220:23whiloWhat would be necessary to derive these type definitions from spec?#2019-10-2220:35whiloI think one problem that core.typed had was that too few people wrote type definitions. A possibly very restricted subset of spec would be better than having your own type definitions. A problem of this approach would be that it can limit the use of spec for users. The restricted definitions could be an overlay that automatically tries to use spec when there is no restricted type definition available. But you are more familiar with the details of spec, I assume I am idealizing a bit.#2019-10-2220:41dominicm@filipematossilva what does the latter mean? I think I meant the former.#2019-10-2221:00Filipe Silvathe latter means making a github action that is triggered by some event in github and performs some piece of code, in this case clj-kondo#2019-10-2221:00Filipe Silvaa common usage of github actions is to automatically add/remove labels in issues/prs#2019-10-2221:01Filipe Silvathe former means adding a github actions for CI check to your commits, where a series of commands is ran and status is displayed on PRs#2019-10-2221:02Filipe Silvaif you want the former, it is mostly a matter of - deciding what OS you want it to run on - deciding on a way to install clj-kondo on that run - running clj-kondo#2019-10-2221:03Filipe SilvaI can help you setup that, can you point me to your repo?#2019-10-2221:11dominicmI wouldn't want to put you out :) I just wanted to poke around and see how that looked in practice.#2019-10-2222:13Filipe SilvaLooks like this
#2019-10-2222:13Filipe Silvahttps://github.com/filipesilva/clj-kondo/actions#2019-10-2222:14Filipe SilvaAnd this is the definition#2019-10-2222:14Filipe Silvahttps://github.com/filipesilva/clj-kondo/blob/master/.github/workflows/nodejs.yml#2019-10-2309:39Marc O'Morain> Unused private var config-compilation.yaml/whitespace-names [141, 2]#2019-10-2309:40Marc O'MorainShould the colum here be 16, rather than 2?
(def ^:private whitespace-names
 ^2            ^16
#2019-10-2309:46borkdudeit's kind of arbitrary I'd say#2019-10-2309:47borkdudeif you're trying to exclude warnings based on position, maybe only use the line number?#2019-10-2309:47borkdudethere has been a recent change to that position for ... reasons 🙂#2019-10-2309:52borkdudeif there is a strong case to change it, I'd like to hear it#2019-10-2309:58borkdudeI tried to make it consistent with joker so if you use both, you see it only in place:
$ clj-kondo --lint /tmp/foo.clj
/tmp/foo.clj:3:1: warning: Unused private var private.tmp.foo/foo
linting took 9ms, errors: 0, warnings: 1

$ joker --lint /tmp/foo.clj
/tmp/foo.clj:3:1: Parse warning: unused var foo (joker)
#2019-10-2309:58Marc O'MorainI do not have a strong case.#2019-10-2309:59Marc O'MorainWhen the squiggle in VSCode is under the def, it makes me think that there is problem with the def form.#2019-10-2309:59Marc O'MorainIf the squiggle were under the var name, I would assume the problem was with the var itself.#2019-10-2310:00borkdudeok, that sounds like a case#2019-10-2310:01borkdudethe way it works now is that the var is defined at that position, so in the export you will also have that position#2019-10-2310:01borkdudeand because the var is defined at that position, the warning also appears there#2019-10-2310:01borkdudebut that could be easily changed probably (while keeping the export the same)#2019-10-2310:02borkdudeI don't have a strong preference#2019-10-2322:04borkdudeplease give it a try: https://marketplace.visualstudio.com/items?itemName=borkdude.clj-kondo this should work for users on Windows as well#2019-10-2323:29sogaiumessages about unresolved symbols and such show up 🙂#2019-10-2323:30sogaiuthough i wonder why i get one for "alias"#2019-10-2406:44borkdudeDo you also get it when running clj-kondo from the command line?#2019-10-2407:20borkdude^ @sogaiu#2019-10-2407:23borkdudeI bet you're in a .cljc file?#2019-10-2407:24borkdude@pez @filipematossilva https://clojurians.slack.com/archives/CHY97NXE2/p1571868283186300#2019-10-2407:27sogaiuyes, that's right#2019-10-2407:28borkdudeyou're getting that error because alias is not valid in CLJS (or at least clj-kondo thinks so). so when you wrap it in a conditional #?(:clj ...) the warning goes away#2019-10-2407:28sogaiuah, ok, thanks. makes perfect sense.#2019-10-2407:30sogaiui wonder why i'm not seeing the same thing via flycheck in emacs#2019-10-2407:31borkdudeI see the same behavior in flycheck+emacs, so it's probably an installation thing#2019-10-2407:34sogaiuah, will investigate#2019-10-2407:57sogaiuyes, it was a local thing. sorry for the noise. i'm not using the vanilla clojure-mode so i should have known 🙂#2019-10-2410:22sogaiuit turned out there was one more twist -- depending on whether i launched emacs from a terminal or not, exec-path was different. that was also an "installation thing", but at a lower level. til -- flycheck automatically disables checkers for various reasons -- M-x flycheck-verify-setup can be of some help, but it seemed convoluted to have to use C-u M-x flycheck-disable-checker to re-enable...#2019-10-2410:22borkdudeyeah. what I also find useful is running flycheck-compile#2019-10-2410:24sogaiuah, that gives more detailed output i guess. nice. thanks for the tip!#2019-10-2410:25sogaiuclj-kondo was my first real reason to use flycheck -- i suppose most other folks who use flycheck-clj-kondo are likely to be flycheck users already?#2019-10-2410:28borkdudeI just use flycheck, but I'm by no means an expert on how to use it#2019-10-2412:44borkdudeThe lsp server should also work with emacs. Maybe with inspiration from @snoe's https://github.com/snoe/clojure-lsp#emacs code people can try it out and see if they can get it working on Windows, document it etc.#2019-10-2412:44borkdudeCode for the lsp server: https://github.com/borkdude/clj-kondo.lsp#2019-10-2413:30sogaiui tried to get clojure-lsp to work with emacs before but didn't have much luck -- i wonder if things have changed...#2019-10-2413:37snoe@sogaiu my coworker is using it with hydra and stuff setup for it. https://github.com/dpsutton/tangled/blob/master/init.org#lsp#2019-10-2413:38borkdude@snoe If you would consider adopting clj-kondo into clojure-lsp, by borrowing some code from https://github.com/borkdude/clj-kondo.lsp it should just be a few lines of code.#2019-10-2413:39borkdudeno hard feelings if you don't of course!#2019-10-2413:39borkdudealso feedback on clj-kondo.lsp is welcome. this was my first time doing anything with lsp#2019-10-2413:48snoe@borkdude let's do it!#2019-10-2413:50sogaiu@snoe -- i will take a look -- just having failed again, happy to have more pointers 🙂#2019-10-2414:09sogaiuah, that config had some extra bits that the repository README seemed to be lacking -- seems to have done the trick -- thanks @snoe! at long last, i can try clojure-lsp 🙂#2019-10-2421:10dominicm (:refer-clojure :rename {requirng-resolve rr}) clj-kondo didn't pick up that I typo'd the left-hand side here. Shall I raise an issue?#2019-10-2421:12borkdudesure!#2019-10-2421:18dominicmhuh, wait. You don't actually seem to warn me if I :refer a non-existent var. I thought it did.#2019-10-2421:21borkdudeit doesn't#2019-10-2421:22borkdudeabout clojure.core we know all the vars, but we don't know all the vars from other namespaces#2019-10-2421:22dominicmunless in the cache?#2019-10-2421:23borkduderight, but it should also work without the cache without giving false positives. it could try to be more clever about it, for sure#2019-10-2421:24borkdudeso if it's in the cache, it could try to help you#2019-10-2421:24borkdudenot sure if this will lead to many false positives, but definitely worth a try#2019-10-2421:24borkdudealso worth an issue#2019-10-2507:19borkdude@filipematossilva added the docs about npm: https://github.com/borkdude/clj-kondo/blob/master/doc/install.md#npm-linux-macos-windows#2019-10-2515:55Filipe Silvasweet 😄#2019-10-2515:55Filipe Silvaregarding clj-kondo + clojure-lsp, that sounds just perfect#2019-10-2515:55Filipe Silvatooling is a super hot topic right now, having all the nice stuff in only a few places is super important#2019-10-2519:26pezIs this reported?#2019-10-2520:09borkdude@pez for me this works:
(ns calva-test
  (:require [cljs.test :refer [is]]))

(is 1)
#2019-10-2520:10borkdudeThis as well:
(ns calva-test
  (:require [cljs.test :refer [is]]))

(defn foo [] (:test (fn [] (is 1))))
So I'll need more info from you. Can you try to lint the file from the command line and if the problem persists, make an issue?
#2019-10-2520:12pezI’m happy to make an issue. Just wanted to see if it was on your radar already. Will try from the command line.#2019-10-2520:12borkdudeit's not on my radar yet, since I need more information, e.g. what message you are seeing 😉#2019-10-2520:22borkdudebut I'm getting curious#2019-10-2520:41pezhttps://github.com/borkdude/clj-kondo/issues/549#2019-10-2520:50borkdude^ @pez you're running a pretty old version of clj-kondo there. could you first try to upgrade? meanwhile I'll look at your example#2019-10-2520:54borkdudeI think this is a duplicate of: https://github.com/borkdude/clj-kondo/issues/526#2019-10-2521:02borkdudeso I answered in the issue. I found one new bug, which will be solved with high priority: https://github.com/borkdude/clj-kondo/issues/550#2019-10-2610:04borkdudeclj-kondo v2019.10.26: - Windows support via LSP and NPM - Major improvement in parser feedback when typing unbalanced parens and more! https://github.com/borkdude/clj-kondo/releases/tag/v2019.10.26#2019-10-2616:34dharriganArch updated.#2019-10-2616:37borkdudethanks!#2019-10-2616:37dharriganyou're welcome! 🙂#2019-10-2711:21p-himikHow do you think - is it reasonable to check that any particular namespace has consistent aliases throughout the project? E.g. one file uses (:require [a.b.c :as c]), another one uses [a.b.c :as x], the third one uses something else.#2019-10-2711:25borkdude@p-himik @dominicm is using the analysis export for this I think#2019-10-2711:25borkdudemaybe he could give you his script#2019-10-2711:26dominicmI didn't write it, but the data is there now. I got a bit hung up trying to figure out a happy integration story.#2019-10-2711:27borkdude@p-himik what I'm referring to is this feature: https://github.com/borkdude/clj-kondo/tree/master/analysis#2019-10-2711:28dominicmI've had discussions internally, and some people are really into "context" of reusing namespace aliases. I don't think this can be in kondo because there's no consensus.#2019-10-2711:30borkdudeIt can be there as an "optional" linter that's turned off by default, just like the "missing docstring" one#2019-10-2711:30borkdudebut it can already be done as a separate script on top of the analysis export, so it doesn't have very high priority#2019-10-2711:32borkdudeunless people start bugging me about it more#2019-10-2711:33dominicmI agree :).#2019-10-2711:33p-himikGot it. Thanks for the discussion!#2019-10-2720:05mynomotoIs there some way to whitelist :refer :all for some namespaces?#2019-10-2720:12borkdudeno#2019-10-2720:14mynomotoOk, thanks. I'm using a strange library that sort of encourages/needs :refer :all and I don't want to turn it off wholesale. But I'm starting to think that turning it of is the best option atm.#2019-10-2720:15p-himikIs it specter by any chance?#2019-10-2720:16borkdudeI'd be curious why/when it would be encouraged. it doesn't work at all in CLJS for example#2019-10-2720:17mynomoto@p-himik No, specter encourages but doesn't require that so I use it with a alias usually.#2019-10-2720:17p-himikYep, that's why after starting using clj-kondo, I had no remorse replacing :use with :require :as. 🙂#2019-10-2720:17p-himikHuh. Why would something need :refer :all?#2019-10-2720:18mynomoto@U04V15CAJ it's https://github.com/viasat/salt and it works this way because it will be transpiled to tla+ and it wants to keep the semantic close to that language.#2019-10-2720:19borkdudeyou can explicitly refer the vars you need with :refer [foo bar]#2019-10-2720:19mynomotoMy attempts of transpilation failed after I changed the require.#2019-10-2720:20borkdudemaybe you should raise an issue with that repo to support aliases?#2019-10-2720:21mynomotoThat would be too different from the way tla+ works I suppose. Being near the output is an objective.#2019-10-2720:22mynomotoBut you are right, I can refer specific symbols and it worked. I think I tried to use alias before and that doesn't work.#2019-10-2720:23borkdude👍#2019-10-2816:00davein general, i avoid using :refer :all, but i do prefer it in rare cases where a library provides a DSL#2019-10-2816:00davee.g. my own library, alda-clj: https://github.com/daveyarwood/alda-clj#2019-10-2816:01davewhen libraries like salt and alda-clj give you a DSL, using :refer :all lets you pretend that all the public vars in a namespace are sort of a part of the clojure language. like you're not writing clojure anymore, you're writing clojure + alda-clj, or whatever#2019-10-2816:02daveit's totally not a good coding practice, in general#2019-10-2816:02davebut i think there are rare use cases#2019-10-2816:03borkdudethanks @U0AHJUHJN, so maybe for these rare cases a rule in clj-kondo would be good then#2019-10-2816:04borkdudeunless the linter already complains about a lot of other stuff as well, that it doesn't know about#2019-10-2816:04davei think it would be useful to have the ability to whitelist namespaces to make them OK to :refer :all#2019-10-2816:04borkdude@U0AHJUHJN what about :refer [x y z]?#2019-10-2816:05daveoh, is the issue with :refer in general?#2019-10-2816:06davei'd have to think about that one a bit#2019-10-2816:06davei don't think :refer [about twenty-five different vars] would help in cases like alda-clj#2019-10-2816:06davethere's a whole standard library of sorts#2019-10-2816:07davewhen i use alda-clj, i'm putting myself in a mindset where i have a whole language available to me, and it's cumbersome to either have to namespace all the vars, or worry about which ones i've explicitly referred in#2019-10-2816:07daveso :refer :all makes a lot of sense to me in that context#2019-10-2816:07davei think another example is clojure.test#2019-10-2816:07borkduderight, and that's probably also the only namespace that you're going to use?#2019-10-2816:08davealthough i typically do explicit refers there, like :refer [deftest testing is are]#2019-10-2816:08borkdudeyes, typically that's true for me as well#2019-10-2816:08borkdudeif you can provide me with some typical alda-clj code, I'd be happy to take a look in an issue for it#2019-10-2816:09davehere's an example: https://github.com/daveyarwood/alda-clj/blob/master/examples/clapping-music#2019-10-2816:10daveand another: https://github.com/daveyarwood/alda-clj/blob/master/examples/entropy#2019-10-2816:11daveto give you an idea of the standard library: https://cljdoc.org/d/io.djy/alda-clj/0.2.2/api/alda.core#2019-10-2816:11borkduderight, makes sense!#2019-10-2816:12borkdudeI'll make an issue for this#2019-10-2816:12daveawesome, thanks a lot!#2019-10-2816:16borkdudehttps://github.com/borkdude/clj-kondo/issues/560#2019-10-2816:16borkdude^ @U05094X3J#2019-10-2816:17borkdudenote: the unresolved symbols for the referred-all namespace go away once clj-kondo has linted the lib namespace and there is a .clj-kondo directory in the project#2019-10-2816:27daveproposal looks great - well captured!#2019-10-2816:28borkdude@U0AHJUHJN if you feel like it, you're welcome to make PR. if you don't feel like it, that's ok too 🙂#2019-10-2903:24mynomotoThat proposal looks great.#2019-10-2720:25mynomotoDo regex work to configure unresolved-symbols?#2019-10-2720:27borkdudeI don't think that works (I had to look it up myself).#2019-10-2720:27borkdudeThis is the relevant documentation: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-unresolved-symbols-from-being-reported#2019-10-2720:31mynomotoYeah, I saw that. I was just wondering if it could be undocumented 😉 Do you think that would be a useful addition?#2019-10-2720:47borkdudeI haven't had this need myself, could you give an example where it makes sense?#2019-10-2803:01mynomotoWell, the same library https://github.com/viasat/salt has a thing where when you create a variable x it creates another x' that is the next step for x. I want to whitelist #".*'$" in this case.#2019-10-2803:02mynomotoBut I'm almost giving up linting this project. It's not really clojure.#2019-10-2808:17borkdudeIf it's just to support this library I would say it's not a strong enough case yet. But you can blacklist certain files in your project so linting is turned off there#2019-10-2808:17borkdude(check the config docs)#2019-10-2814:58mynomotoOk, thanks!#2019-10-2809:39whilo@borkdude what would be necessary to provide a linter for the datalog query DSL arguments to datomic, datahike or datascript's q function?#2019-10-2809:40whilo@kordano this would probably pay off for our development work already#2019-10-2809:41borkdudeI think the following: 1) determine which fully qualified function calls need datalog linting 2) write a function that lints the datalog expression 3) combine 1 and 2 4) write unit tests 5) profit!#2019-10-2809:42borkdudenote that clj-kondo works with nodes instead of direct sexps values, but you can convert a node into it's corresponding sexp.#2019-10-2809:42borkdudebut it's preferable to work with nodes directly as you can be more specific in error locations and you can detect errors in the representation that would not even compile#2019-10-2809:43borkdude^ @whilo#2019-10-2809:43borkdudeI'd be happy to stub out the start of this issue so you can fill in the rest of the details#2019-10-2809:45whilook, cool. i can easily provide a function that calls the datalog parser and returns either an error or whatever truthy value required#2019-10-2809:47borkdudefeel free to create an issue, some examples of expected inputs + errors and a link to that function#2019-10-2809:47borkdudeI might have to port that function to clj-kondo or use it directly, depends.#2019-10-2816:21davehttps://clojurians.slack.com/archives/CHY97NXE2/p1572175726225800 ^this was an interesting discussion, wanted to offer my 2¢ i think i can't even reach a consensus with myself on this one! sometimes i like the aliases all being uniform, and in some cases, i like to be able to name them differently imagine if you have a foo.api namespace that has been superceded by a foo.api2 namespace now imagine that you have a bar namespace that used to consume the foo.api namespace, so the ns declaration included [foo.api :as api]. and imagine that you want to migrate to the newer foo.api2, but the situation is kind of hairy and you need to still depend on something from foo.api too, for a while. so now bar needs to depend on both foo.api and foo.api2 we actually have a scenario like that at work, and we addressed it by requiring [foo.api2 :as api] and [foo.api :as oldapi]#2019-10-2816:22daveso the issue there is that foo.api is aliased as api in some namespaces, and oldapi in others#2019-10-2816:22borkdudeand you would like to have them consistent?#2019-10-2816:23borkdudebecause it's an error to use oldapi?#2019-10-2816:23davei think i like being able to use a different alias for foo.api in different namespaces, because i'm bringing it in within a different context#2019-10-2816:24davelike in some namespaces, foo.api really is the "api," in others it's the "old api"#2019-10-2816:24borkdude@dave well, there is the analysis export and you can write any kind of script with 2-for-Tuesday's in it that you want 🙂#2019-10-2816:24davei think that's a good solution 😄#2019-10-2816:24davei agree with dominic that there isn't consensus about this#2019-10-2816:52dominicm@dave I would be very sad working on that. I'd never know if I could trust whether what I was looking at would do what I expected, because it might be old or new api. So I'd be constantly jumping to the ns form to remind myself any time I was looking at code using either.#2019-10-2817:09borkdudeyeah, I guess you could just call the old api old-api/ everywhere#2019-10-2817:11dominicmI'd be fine with api2 for the new one until fully migrated. Although a linter would help me trust that people have done the right thing with being consistent.#2019-10-2817:59davehmm, that's a good point. i think i like the idea of the linter telling you about inconsistencies, and therefore encouraging you to come up with different aliases for different namespaces#2019-10-2817:59davei.e. don't call the old api "api" if there is also a new api that is being called "api" elsewhere#2019-10-2818:01davehmm, which raises an interesting question... if i have a namespace that requires pears :as p, and then another namespace that requires peaches :as p, is that a problem?#2019-10-2818:01daveor is it just that you can't have pears :as p in one namespace, and pears :as pr in another namespace?#2019-10-2818:01davei'm thinking it's the latter#2019-10-2818:16dominicmp should be consistent in what it refers to. So I'd go with "both".#2019-10-2818:24davei'm pretty sure i agree#2019-10-2818:24daveas you're working in a project, you come to learn what p/ means in general#2019-10-2818:24daveso you don't have to keep referring back to the ns form in whatever file you're editing#2019-10-2818:39borkdudestarting to make sense#2019-10-2818:39borkdudewhat about libraries on the classpath? clj-kondo doesn't know what's a library and your own code#2019-10-2818:40borkdudeof course you can lint different directories with different configurations#2019-10-2818:41davei don't think you would want to apply these rules across "projects"#2019-10-2818:41borkduderight, I mean when you do clj-kondo --lint $(lein classpath)#2019-10-2818:41davelike if i'm using cheshire, and cheshire refers in clojure.string as s, then i don't want to not be able to call something else s in my project#2019-10-2818:41borkdudebut you do that only to populate the cache, so that's fine, you can ignore the warnings there#2019-10-2818:42daveoh, hmm#2019-10-2818:47borkdudeso this could be a linter, I guess 🙂#2019-10-2818:50borkdudehttps://github.com/borkdude/clj-kondo/issues/561#2019-10-2818:51borkdudefeel free to comment on it and to provide ideas, alternatives#2019-10-2818:53borkdudemaybe the value in the config map should also be a map so it can take options, like: except in this namespace#2019-10-2818:54borkdudebut maybe the point of this linter should be that it's consistent without exceptions 😉#2019-10-2818:55davei have a comment -- will add it to the issue#2019-10-2819:05borkdudeadded a comment#2019-10-2819:12borkdudeadded one more#2019-10-2822:29borkdudehttps://github.com/borkdude/clj-kondo/blob/master/doc/dev.md#2019-10-2822:29borkdude^ added some developer docs (design principles, but also practical things like how do you get a REPL)#2019-10-2909:57whilo@borkdude could i just plug it in somewhere like in the tests here: https://github.com/lambdaforge/datalog-parser/blob/master/test/datalog/parser_test.cljc ?#2019-10-2910:00borkdude@whilo I made an issue for datalog linting here now: https://github.com/borkdude/clj-kondo/issues/563#2019-10-2910:01whilook, cool. thanks#2019-10-2910:05borkdudeit might make sense to only include the verification/linting bits from that library and port it to clj-kondo instead of including this as a dependency into clj-kondo#2019-10-2917:51whilowe want that too, the parser is already minimal and is factored out of datahike for exactly such syntactic operations. it has no dependencies itself.#2019-10-2918:40borkdudeAlright. If clj-kondo would straight up use this, I guess you can only assert that something is wrong with the query and then only point at the query as a whole and not at one symbol inside the query.#2019-10-2918:41borkdudeUnless we preserve location metadata while coercing it to a sexpr#2019-10-2918:41borkdudeThat might work#2019-10-2910:05borkdudeI want clj-kondo to have the least amount of deps as possible#2019-10-2914:17Marc O'Morain❤️#2019-10-2914:17Marc O'Morain#2019-10-2917:51whilowe want that too, the parser is already minimal and is factored out of datahike for exactly such syntactic operations. it has no dependencies itself.#2019-11-0120:05borkdudeI would appreciate it if someone could go through the steps in this issue to verify if it's clear to reproduce: https://github.com/oracle/graal/issues/1804#2019-11-0120:07sogaiuCLJ_KONDO_VERSION probably needs to be filled in with some value, right?#2019-11-0120:08borkdudethanks, edited#2019-11-0120:10sogaiuwe also need a reflection file i think#2019-11-0120:12borkdudeadded#2019-11-0120:18sogaiucd project -> cd /tmp/project ?#2019-11-0120:19borkdudeedited#2019-11-0120:19borkdudemade the wrong edit, corrected#2019-11-0120:23sogaiulol, i'm not sure i've ever waited this long for dependencies to finish downloading 🙂#2019-11-0120:24sogaiumy lein classpath execution fails at:
Could not transfer artifact binaryage:env-config:pom:0.2.0 from/to clojars (): Read timed out
This could be due to a typo in :dependencies, file system permissions, or network issues.
If you are behind a proxy, try setting the 'http_proxy' environment variable.
#2019-11-0120:25sogaiua subsequent invocation prints a classpath#2019-11-0120:26sogaiuextra double quote at end of:
./clj-kondo --lint "$(lein classpath)" > /tmp/log.txt"
?
#2019-11-0120:27sogaiui did not observe an exception for:
./clj-kondo --lint "$(lein classpath)" > /tmp/log.txt
#2019-11-0120:28sogaiufwiw:
$ native-image --version
GraalVM Version 19.2.1 CE
#2019-11-0120:28sogaiubbiab#2019-11-0120:43lreadI can take a pass as well, if that helps.#2019-11-0120:45borkdudemaybe I should try the upgrade to 2.1#2019-11-0120:45borkdudesure @lee#2019-11-0120:51lreadnot that it is terribly important but https://github.com/oracle/graal/files/3799384/clj-kondo-2019.10.26-standalone.jar.zip contains __MACOSX dir
> unzip -l ~/Downloads/clj-kondo-2019.10.26-standalone.jar.zip
Archive:  /Users/lee/Downloads/clj-kondo-2019.10.26-standalone.jar.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
  8704607  11-01-2019 15:35   clj-kondo-2019.10.26-standalone.jar
        0  11-01-2019 15:45   __MACOSX/
      985  11-01-2019 15:35   __MACOSX/._clj-kondo-2019.10.26-standalone.jar
---------                     -------
  8705592                     3 files
#2019-11-0120:52borkdudeI'm still experiencing the problem with the upgrade to graalvm 19.1.2#2019-11-0120:53borkdudeyeah, that's an artifact of zipping the jar on my machine, can ignore that#2019-11-0120:53lreadAlso kind of obvious, but you might want to replace "Build the following .jar" to "Unzip then build the following .jar"#2019-11-0120:54lreadI don't see the version of Graal you are testing against in the issue.#2019-11-0120:54borkdudenote added#2019-11-0120:55borkdudeAdded#2019-11-0120:56borkdudealso added MacOS 10.14.6#2019-11-0120:56borkdudewhich I am using and also the original reporter#2019-11-0120:56lreadas someone walking through the issue it would be helpful to have the reflection.json come before the command because the native-image command requires it.#2019-11-0120:57borkdudedone#2019-11-0120:57borkdudeit would be interesting to discover if linux users didn't have this problem#2019-11-0120:57lreadIs $NATIVE_IMAGE common? if not just replace with native-image#2019-11-0120:58borkdudegood point, done#2019-11-0120:58sogaiuwas using linux, and also used plain native-image#2019-11-0120:58lreadyou no longer need "where $NATIVE_IMAGE..."#2019-11-0120:59borkdude@sogaiu could you try this also with the binary from github, and/or on a macos machine?#2019-11-0120:59borkdudeif you don't trust the binary from github, then ignore my request 🙂#2019-11-0121:00lreadam using macos#2019-11-0121:00sogaiulol, just don't have access to macos for a few weeks#2019-11-0121:00borkdudecool lread, I'm awaiting your findings#2019-11-0121:01sogaiubtw which binary do you mean?#2019-11-0121:01borkdude@sogaiu one you can download here: https://github.com/borkdude/clj-kondo/releases#2019-11-0121:02borkdudescroll to 'assets'#2019-11-0121:02sogaiuah, ok#2019-11-0121:02sogaiuwill try when i get back#2019-11-0121:04lreadin your code snippet, comment # this directory will be used to create a RandomAccessFile in might not be finished or has extra word in?#2019-11-0121:05borkdudeit will be used to create a file in#2019-11-0121:05borkdude"to put it in"#2019-11-0121:06lreadoh how about "# a RandomAccesFile will be created in this directory"#2019-11-0121:07lread(original confused me, might confuse reviewer)#2019-11-0121:07borkdudeexcellent, done#2019-11-0121:08lreaddelete trailing double quote in code snippet?: ./clj-kondo --lint "$(lein classpath)" > /tmp/log.txt"#2019-11-0121:09borkdudedone#2019-11-0121:12lreadsuccessfully reproduced FileNotFoundException#2019-11-0121:13sogaiudid your lein classpath succeed without problems?#2019-11-0121:14borkdudethank you lread. That is also on MacOS right? which version?#2019-11-0121:14borkdudeAnd could you also verify that the problem does not occur when linting with the jar?#2019-11-0121:16lreadam on that last step now... should mention that java -jar ... command should executed from /tmp/project as it needs project.clj#2019-11-0121:16lreadand maybe.. redirect output from java -jar to different log file as to not overwrite previous results.#2019-11-0121:17lreadalso mention that an exit code of 3 is expected for java -jar ...#2019-11-0121:17borkdudethe results are not important and probably the log file from the first step is completely empty#2019-11-0121:18borkdudethe only important thing is the exception. the error code is probably on me for not catching the exception from the main function, so not for them to sort out#2019-11-0121:18borkdudeit's a clj-kondo thing#2019-11-0121:18lreadright.#2019-11-0121:19lreadmaybe route to /dev/null then.#2019-11-0121:19lreadto be super clear it is not a variable.#2019-11-0121:19lreadjust humble suggestions of course#2019-11-0121:19borkdudeoh I get what you mean with the exit code: they should ignore it even it it's not zero#2019-11-0121:20borkdudegood suggestions#2019-11-0121:21borkdudeupdated#2019-11-0121:22lreadI am running macOS 10.15 (19A602)#2019-11-0121:22lread(that thing in brackets seems new? apparently is the build number)#2019-11-0121:23borkdudeadded your version to the issue as well#2019-11-0121:23borkdudeisn't 19a602 a machine model?#2019-11-0121:23lreadso that's it full walkthrough of issue done. looks good.#2019-11-0121:23borkdudeah it's a supplemental update probably#2019-11-0121:23lreadlooks like it eh? apparently is build number: https://support.apple.com/en-is/HT201260#2019-11-0121:24borkdudeso no exception using the .jar?#2019-11-0121:24lreadno exception, exited with code 3#2019-11-0121:24borkdudesuper helpful. so far it only seems to happen on MacOS#2019-11-0121:25borkdudemaybe it has to do with too many file handles or something, don't know, low level stuff!#2019-11-0121:25lreadyeah, just started playing with graal today, a big bucket of mystery to me!#2019-11-0121:26lreadyour projects are good references for graalvm thanks!#2019-11-0121:27borkdudejet might be the simplest one of the bunch to look at#2019-11-0121:27lreadhmmm just noticed macOS 10.15.1 is available, I doubt that would make a difference for your issue...#2019-11-0121:27borkdudebut they are compiled more or less the same, using lein uberjar + the script/compile script#2019-11-0121:28lreadya, super helpful. I'm going the tools deps route, and figured out what I need for that today.#2019-11-0121:29borkdudenote that I went that route before, but had reasons to go to lein#2019-11-0121:30borkdudebut feel free to explore 🙂#2019-11-0121:30lreadhmm... interesting! uberjaring is certainly more straightforward with lein.#2019-11-0121:30borkdudebasically because lein had better capabilities for AOT compilation#2019-11-0121:30borkdudeboot might do it good as well#2019-11-0121:31borkdudebut I found nothing that came close to this using deps.edn. sogaiu mentioned an interesting tool recently which might do it#2019-11-0121:32borkdudeah it was this one: https://github.com/EwenG/badigeon#2019-11-0121:32lreadcambada has support for native: https://github.com/luchiniatwork/cambada#2019-11-0121:32lreadso many competing packagers for tools deps. it is confusing.#2019-11-0121:33borkdudeyeah well there's also clj.native-image, but I ran into limitations. basically all tools which wrap the native-image command will be limiting, in my experience an AOT-ed uberjar + shell script works better
#2019-11-0121:34borkdudein that wrappers are limiting by definition#2019-11-0121:34borkdudeor confusing, sometimes, at the least#2019-11-0121:34lreadagreed#2019-11-0121:35lreadI am using currently using depstar to build my jar and am following instructions for aot compiling from here: https://clojure.org/reference/compilation#_gen_class_examples#2019-11-0121:36lreadI have used maven to build my jars in the past.#2019-11-0121:36borkdudeone problem I ran into with clj.native-image was that it tried to compile my namespaces, but somehow missed a few or didn't do it in the right order#2019-11-0121:36lreadI'm sure I'll hit problems, my graalvm playground only has 2 namespaces!#2019-11-0121:36borkdudeI also ran into problems with it on Windows. Eventually I made a script/compile and script/compile.bat#2019-11-0121:38lreaddid you consider compiling your tests with graal (along with your src) and running them that way? I think that's the approach typically taken for plain old cljs testing.#2019-11-0121:43lreadmight not make sense for your command line tools... but for a pure library without a command line.. maybe?#2019-11-0122:05borkdude@lee No, I run the tests from the JVM, but only change the way how to call the thing under test. When doing native I call the binary using clojure.shell/sh#2019-11-0122:06borkdudeAlso for libraries, I just make a main that I test (see e.g. sci)#2019-11-0122:06lreadyes, understood, that makes sense for sci and jet#2019-11-0122:07sogaiuno exception when using downloaded binary, fwiw#2019-11-0122:07borkdude@sogaiu thanks, that re-inforces the hypothesis that it's specific to macOS#2019-11-0122:08borkdude@lee Are you thinking about tests for rewrite-cljc in this case?#2019-11-0122:08lreadyeah, I should move this convo over to #rewrite-clj#2019-11-0122:09lreador maybe #graalvm#2019-11-0122:09borkdudeI don't mind 😉#2019-11-0122:09lreadyou are a gentle moderator simple_smile#2019-11-0122:10borkdudeI haven't tried compiling clojure.test to GraalVM but if that works, then that's a fine approach I'd say.#2019-11-0122:11lreadI think it might make sense for rewrite-cljc - if it works!#2019-11-0122:13borkdudeI haven't got any GraalVM tests in edamame, but since I'm using that extensively in sci and babashka, I test it that way#2019-11-0122:14lreadyeah makes sense#2019-11-0122:17lreadbtw, I just upgraded to macOS 10.15.1 (19B88), same result for your graal issue.#2019-11-0122:20borkdudethanks, added the version to the issue#2019-11-0122:20borkdudewhat's weird is that the size of the classpath makes a difference for getting a FileNotFoundException#2019-11-0122:21borkdudeand only on macOS :thinking_face:#2019-11-0122:22lreadit is a puzzle#2019-11-0122:33lreadI suppose, if you were curious, you could do some println debugging prior to opening the file... check what returns you get for .exists and .canRead, maybe try .getAbsolutePath.#2019-11-0122:42borkdudethat's a good suggestions. this API should work even when the file doesn't exist yet, but it's good to add that debugging.#2019-11-0212:01lreadah, ok, makes sense#2019-11-0212:38lread@U04V15CAJ, I’m actually looking at the code https://github.com/borkdude/clj-kondo/blob/f6ab3624defa04708887bc9687805b4303f5dbb4/src/clj_kondo/impl/cache.clj#L58 don’t you need a .close somewhere for that RandomAccessFile?#2019-11-0212:44borkdudeMaybe that would be good. So then this part would be wrapped in with-open: https://github.com/borkdude/clj-kondo/blob/f6ab3624defa04708887bc9687805b4303f5dbb4/src/clj_kondo/impl/cache.clj#L65#2019-11-0212:47lreadyeah, just a guess but problem occurs when classpath is long, so maybe the misleading file not found exception due to a resource leak blowing some os limit?#2019-11-0212:49borkdudeI'll try this#2019-11-0212:49borkdudeit doesn't hurt to add it anyway#2019-11-0212:53borkdudedidn't help, but I'll keep it in#2019-11-0212:53borkdudeI'll merge it to master shortly#2019-11-0212:57borkdudemerged#2019-11-0122:43borkdudehttps://docs.oracle.com/javase/7/docs/api/java/io/RandomAccessFile.html#RandomAccessFile(java.io.File,%20java.lang.String)#2019-11-0122:44borkdudeso .exists returning either true or false doesn't say that much, since it "should just work TM" in both cases#2019-11-0122:45sogaiufor a bit of extra confidence, i went through the issue steps on an ubuntu vm (though with the binary downloaded from releases) -- no exception in the vm either#2019-11-0122:45sogaiucertainly lots of having to restart lein classpath though#2019-11-0122:46borkdudeit's probably a GraalVM/macOS substitution problem for PosixUtils.java or something#2019-11-0122:46sogaiuah -- it's probably totally unrelated, but i keep hearing on #shadow-cljs about jvm issues on macos#2019-11-0122:48borkdudewhat could be tried is not only retrying the locking of the file, but also the creation of the file:
(defmacro with-cache
  "Tries to lock cache in the scope of `body`. Retries `max-retries`
  times while sleeping 250ms in between. If not succeeded after
  retries, throws `Exception`."
  [cache-dir max-retries & body]
  `(let [lock-file# (io/file ~cache-dir "lock")
         _# (io/make-parents lock-file#)
         raf# (RandomAccessFile. lock-file# "rw")
         channel# (.getChannel raf#)]
     (loop [retry# 0]
       (if-let [lock#
                (try (.tryLock channel#)
                     (catch java.nio.channels.OverlappingFileLockException _#
                       nil))]
         (try
           
#2019-11-0122:49borkdudebut that would only mask the underlying problem#2019-11-0122:50borkdudewhich is unknown yet#2019-11-0210:57Filipe Silva@snoe @borkdude heya, I wanted to talk to you about making a npm distro of clojure-lsp in the same way I made one for clj-kondo#2019-11-0210:57Filipe Silvaso the clj-kondo one felt like it made sense because it would be ran standalone in non-server mode#2019-11-0210:57Filipe Silvadoes clojure-lsp have a non-server mode?#2019-11-0210:58Filipe Silvaif it doesn't, I wonder if it makes sense to have a npm distribution... because it feels like something that actually runs as a editor extension instead#2019-11-0210:58Filipe Silvaand from looking at the clj-kondo editor extension, it doesn't seem to need a npm distro#2019-11-0211:00Filipe Silvashould the focus instead be to provide a clojure-lsp vscode extension similar to the clj-kondo one? would it make sense for them to be the same extension even?#2019-11-0212:09borkdude@filipematossilva Let's back up a bit. The clj-kondo.lsp + vscode extension are available from the VSCode marketplace. What would be the added benefit of an npm package?#2019-11-0212:10Filipe Silvayes I suppose that is the main question#2019-11-0212:10Filipe Silvato give npm consumers a cross platform way to run closure-lsp#2019-11-0212:11Filipe Silvanot sure who those consumers would be though#2019-11-0212:11Filipe Silvarelevant to note that the closure-lsp vscode extension doesn't work on windows (or didn't, last I checked)#2019-11-0212:11borkdudeit should work on Windows as it's just running a JVM, nothing native. @pez checked that it worked on Windows#2019-11-0212:12borkdudeI could see distributing clj-kondo.lsp as a library on clojars being useful, so others can build extensions for other editors if they want. That's something I'm considering#2019-11-0212:13borkdudethe whole point of clj-kondo.lsp was Windows actually, since the binary already worked on other platforms#2019-11-0212:16borkdudeso maybe you could re-test it @filipematossilva on Windows?#2019-11-0212:16borkdudeit does require a java installation to be available on the path#2019-11-0212:18Filipe Silvaabout a week ago I tried opening the extension and the changelog said it didn't work on windows yet#2019-11-0212:19borkdudewhich changelog?#2019-11-0212:19Filipe Silvathe clojure-lsp vscode extension one#2019-11-0212:20Filipe Silvatrying to find it again, but having trouble... sec#2019-11-0212:20borkdudecan you make a screenshot, so I know what you're seeing?#2019-11-0212:20borkdudeoh clojure-lsp, sorry, I thought you meant clj-kondo.lsp!#2019-11-0212:20borkdudethe VSCode extension borkdude.clj-kondo should work on Windows#2019-11-0212:20Filipe Silvaah no, the clj-kondo vs code extension is working on windows already#2019-11-0212:21Filipe Silvait's the clojure-lsp one that doesn't#2019-11-0212:23borkdudesorry for the confusion#2019-11-0212:41pezclj-kondo.lsp solves more than just the Windows case. It also lets makes the story for vscode clojure linting be the beautifully simple: “Install the cljs-kondo extension”, or even “Install Calva. Oh, you already did that? You have linting.“.#2019-11-0212:43borkdudeyeah 🙂#2019-11-0213:05borkdude@lee I have a debug-lock-file branch now and added the suggested println#2019-11-0213:06borkdudethis works:
$ ./clj-kondo --lint - <<< '(inc)'
exists? false
can-read? false
<stdin>:1:1: error: clojure.core/inc is called with 0 args but expects 1
#2019-11-0213:06borkdudebut with the large classpath I don't even see those printlns:
$ ./clj-kondo --lint "$(lein classpath)"  > /tmp/log.txt
java.io.FileNotFoundException: /private/tmp/lock-kondo/.clj-kondo/.cache/2019.10.27-SNAPSHOT/lock
#2019-11-0213:11borkdudegoing to add some moar debugging#2019-11-0213:13borkdudeno output, still same exception. weird! https://github.com/borkdude/clj-kondo/blob/3c58801d002beb5295ea26264a73dcda09d4cc98/src/clj_kondo/impl/cache.clj#L58#2019-11-0213:55lreadyou might consider adding (flush) after your printlns#2019-11-0213:58lreadjust to be sure your output is is flushed even on exception#2019-11-0214:27borkdudetried that 🙂#2019-11-0214:27borkdude(see branch)#2019-11-0214:29borkdudebut println already calls flush itself too#2019-11-0215:13borkdude@lee @sogaiu found it! it has to do with not closing the JarFile objects 🙂#2019-11-0215:13borkdudestrangely completely elsewhere in the code than where it was reported, maybe due to laziness or something#2019-11-0215:15borkdudeso it had to do with not closing something after all, thanks for the hint @lee#2019-11-0215:32borkdude@rickmoynihan finally found the cause for an issue you were seeing back in September: https://clojurians.zulipchat.com/#narrow/stream/180378-slack-archive/topic/clj-kondo/near/174962809 See https://github.com/borkdude/clj-kondo/issues/542 I just merged a fix to master. This binary should fix the problem: https://6819-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.10.27-SNAPSHOT-macos-amd64.zip#2019-11-0215:32borkdude@lee could you try that one too since you're on Mac?#2019-11-0215:34borkdude@rickmoynihan It was the problem with: > I’ve mkdir .clj-kondo and when running `clj-kondo --lint “$(lein classpath)” I get the error:#2019-11-0215:38borkdudeupdated this issue as well: https://github.com/oracle/graal/issues/1804#2019-11-0215:40borkdudeI'm so happy this weird bug is now solved (at least on my machine, fingers crossed). Thanks a lot for collaborating.#2019-11-0215:49rickmoynihan@borkdude 🍾 great news. So was the issue laziness holding jar files open for too long? Also just tried to recreate the issue but no longer can… weird.#2019-11-0215:50borkdudeWell, because of laziness you can't close a resources, because then you will close it too soon. So I had to make reading sources from a jar strict + close it after reading it.#2019-11-0215:53rickmoynihanyeah, I’ve done that myself but with zip files in the past… laziness and resources don’t mix! 😀#2019-11-0215:53borkdudeexactly the same problem 🙂#2019-11-0215:51borkdude@rickmoynihan It depends on the amount of dependencies. Try this project.clj: https://github.com/borkdude/clj-kondo/files/3799357/project.clj.zip#2019-11-0215:52borkdudeI might try a transducer approach in the future, but for now this works well enough#2019-11-0215:54rickmoynihanyeah a transducer might make sense — but probably not worth the effort porting#2019-11-0215:54borkdudeI guess reading all the sources from a jar in memory at once isn't adding up to enough making it worth porting#2019-11-0215:55borkdudebut a fun exercise, so low priority#2019-11-0215:55rickmoynihanoh it’s slurping… I guess most clojure projects are pretty small, even with all their transitive deps.#2019-11-0215:56borkdudeyeah, it's slurp. could make that into a reader-type thing, but I guess even with this classpath size it doesn't even add up#2019-11-0215:56rickmoynihanbut yeah might be worth porting one day after all… though I don’t see myself maintaining 1m lines of clojure in a project for a while.#2019-11-0215:57borkdudealso linting the classpath is a thing people do once every so often, the most common use case is linting one file at a time#2019-11-0216:09lreadgiving it a go on macOS now...#2019-11-0216:09lread(congrats btw!)#2019-11-0216:14lreadlooks good! also compared output from both and looks good:
> diff native.out jvm.out
4485c4485
< linting took 23197ms, errors: 1582, warnings: 2902
---
> linting took 16499ms, errors: 1582, warnings: 2902
#2019-11-0216:15borkdudethanks 🙂#2019-11-0216:15lreadmy pleasure#2019-11-0216:21rickmoynihanweird that project.clj seems to work for me…#2019-11-0216:21borkdudewith the old binary on MacOS?#2019-11-0216:25rickmoynihanyeah#2019-11-0216:26rickmoynihanwell I’m not sure it’s the same binary I used when I first reported the issue; but I’ve not updated to the binary you posted today.#2019-11-0216:29borkdudeok well, thanks for testing. I have two different macOS machines confirming that it's fixed now 🙂#2019-11-0216:51borkdude@lee @sogaiu I now updated the GraalVM issue using a pure Java example: https://github.com/oracle/graal/issues/1804#issue-516316985#2019-11-0216:52borkdudeMaybe it would be fun if you could also try it#2019-11-0217:07borkdudeTo see how it behaves on your machines#2019-11-0217:16sogaiu@borkdude i got:
Exception in thread "main" java.lang.NullPointerException
	at LockRepro.listFiles(LockRepro.java:13)
	at LockRepro.listFiles(LockRepro.java:25)
	at LockRepro.listFiles(LockRepro.java:25)
	at LockRepro.listFiles(LockRepro.java:25)
	at LockRepro.listFiles(LockRepro.java:25)
	at LockRepro.listFiles(LockRepro.java:25)
	at LockRepro.main(LockRepro.java:33)
#2019-11-0217:16borkdude(it also shows how easy it is to create a binary from a single Java file)#2019-11-0217:16lreadjava LockRepro.java should be javac LockRepro.java#2019-11-0217:16sogaiuyes, i had to do what lread said too#2019-11-0217:16borkdudecorrected#2019-11-0217:17sogaiuneat about creating a binary so easily#2019-11-0217:17borkdudethe resulting binary is 2.6mb#2019-11-0217:17sogaiuthat's about how big it is here too#2019-11-0217:18borkdude@sogaiu since you're getting the exception now, my hunge is that the maximum number of open files for a process on macOS is lower than on linux?#2019-11-0217:18sogaiuthat sounds familiar -- and like what i hear in #shadow-cljs iirc#2019-11-0217:19lreadgot similar result to yours for native:
> ./lockrepro | wc -l
Exception in thread "main" java.lang.NullPointerException
	at LockRepro.listFiles(LockRepro.java:13)
	at LockRepro.listFiles(LockRepro.java:25)
	at LockRepro.listFiles(LockRepro.java:25)
	at LockRepro.listFiles(LockRepro.java:25)
	at LockRepro.listFiles(LockRepro.java:25)
	at LockRepro.listFiles(LockRepro.java:25)
	at LockRepro.main(LockRepro.java:33)
     253
#2019-11-0217:19lread670 jars created for jvm for me.#2019-11-0217:19borkdudewhat do you guys see when executing: $ ulimit -n#2019-11-0217:19sogaiu1024#2019-11-0217:19borkdudeI see 256#2019-11-0217:19lread256#2019-11-0217:19borkdudeah that explains it then probably#2019-11-0217:20lreaderror sucks though#2019-11-0217:20lreador at least misleads#2019-11-0217:20borkdudeindeed it does#2019-11-0217:22sogaiui suppose you might test by changing your limits?#2019-11-0217:22lreadnative succeeds after ulimit -n 1024#2019-11-0217:22sogaiuso quick 🙂#2019-11-0217:22borkdudemaybe related: https://github.com/oracle/graal/issues/1581#2019-11-0217:24borkdudetl;dr: error caused by too many open files, but the error thrown is misleading#2019-11-0217:24lreadyep#2019-11-0217:25lreadso it does not apply to jvm version because... ?#2019-11-0217:27sogaiuiiuc, graal uses a patched jdk -- may be that's related?#2019-11-0217:27sogaiuno, that's probably not it#2019-11-0217:28sogaiunative-image binaries are diff beasts than the actual jvm#2019-11-0217:28borkdudethey do use "substitutions" as they call it: https://github.com/oracle/graal/blob/519cb180a31c61f7735d64aeabf566236489ddcf/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java#2019-11-0217:32borkdudeI was considering to do parallel linting. I can change mapcat into pmap + cat. But maybe I would also run into "too many open files" with this 🙂#2019-11-0217:34borkdudeprobably not though, 8 threads would just mean 8 open files#2019-11-0217:35lreada process must be able to set its own limit no? maybe through setrlimit... maybe there is a graal option for that?#2019-11-0217:36lreadoh maybe you could do in java? here's some graal code that plays with the limit https://github.com/oracle/graal/blob/519cb180a31c61f7735d64aeabf566236489ddcf/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java#L81#2019-11-0217:38lreadgotta run some errands, later! 👋#2019-11-0217:38borkdudelaterz!#2019-11-0318:58lreadI did a small amount of poking around with regards to max files. It seems there is a bit of weirdness around macOS https://github.com/neo4j/neo4j/issues/11739#issuecomment-421333078. I thought maybe graal could be influenced by MaxFDLimit but did not find a way. one thing to note is that ulimit affects process and sub-process so a work-around might be to wrap like so:
#!/usr/bin/env bash
set -eou pipefail
ulimit -n 10000
./lockrepro
#2019-11-0319:02borkdudeyeah, I think the main issue with graal is that it doesn't throw the right exception/message when you hit the limit#2019-11-0319:41lreadagreed#2019-11-0319:54borkdudeclj-kondo v2019.11.03: https://github.com/borkdude/clj-kondo/releases/tag/v2019.11.03#2019-11-0321:20Aleedi'm getting an No matching clause: :boot in a build.boot file. is there a way to fix typing for this file, or at least disable the error?#2019-11-0321:45borkdude@alidcastano I assume this is inside some editor integration?#2019-11-0321:47borkdudeor is this from the command line?#2019-11-0321:48borkdudeIf you're using flymake instead of flycheck in emacs, there's now a plugin for it: https://github.com/turbo-cafe/flymake-kondor#2019-11-0321:51Aleed@borkdude i'm using vscode's calva extension#2019-11-0321:52borkdude@alidcastano Thanks, I'll make a fix.#2019-11-0322:01borkdude@alidcastano should be fixed in plugin version 0.0.8#2019-11-0322:02borkdudefalse positives are expected in build.boot files, because it uses non-standard functions names that aren't imported using a namespace form, but at least you won't get this error anymore#2019-11-0322:03borkdudeclj-kondo could try to improve on linting build.boot files though#2019-11-0322:09borkdudeMade an issue for that: https://github.com/borkdude/clj-kondo/issues/579#2019-11-0322:13pezThere seem to be some special handling of project.clj files in place, right?#2019-11-0322:14pezMaybe it just ignores anything in the defproject form?#2019-11-0322:23borkdudeit ignores unresolved symbols in project.clj#2019-11-0322:23borkdudethere might be errors that it will still detect, like maps with duplicate keys#2019-11-0322:24borkdudeit doesn't do any syntax checking special to leiningen, although that could be added#2019-11-0411:17martinklepsch@borkdude did you see tree-sitter? https://www.youtube.com/watch?v=Jes3bD6P0To, maybe it’s interesting to clj-kondo somehow#2019-11-0411:27borkdudeI haven't seen it, but added it to my watch list. Thanks!#2019-11-0411:37martinklepschSome very cool stuff going on there. To provoke some more interest: the system they built can parse code incrementally, maintaining a full syntax tree by incorporating edits from the user as they come in. It can also parse invalid code, recovering from syntax issues in subtrees/leaves of the AST.#2019-11-0411:50borkdudeIt seems LSP can also do that (parse incrementally)#2019-11-0411:52martinklepschYeah, he also references LSP but considers that both complement each other, tree-sitter sitting at the super low-latency spectrum needed for anything that requires “as you type” kind of interactivity#2019-11-0411:55borkdudetrue, I guess LSP is only a high level protocol. using LSP you can pass the text to a parser, which could be tree-sitter#2019-11-0412:15dominicmLSP is considered too high latency for the things tree sitter is achieving. E.g. Syntax highlighting#2019-11-0412:17borkdudeI guess it depends what you're doing with your LSP events. LSP itself is just a network/REST thing using JSON, which is fast.#2019-11-0412:17borkdudeHow do they define low latency, which threshold in ms are we talking about?#2019-11-0412:32martinklepschI guess 60fps? i.e. double digit ms#2019-11-0412:32martinklepsch(in an ideal world 😛)#2019-11-0412:32dominicm> - The LSP probably isn't well suited to general syntax highlighting due to computation cost and communication chattiness concerns, but the LSP may eventually support semantic syntax highlighting [1]. This could, for example, allow an editor to color all singletons hotpink, which requires a semantic understanding of the code. Semantic highlighting would augment the base highlighting provided by tree-sitter or by a TextMate grammar. Syntax highlighting targets instant. as plugins will be using it to make decisions.#2019-11-0412:33dominicm10k loc buffer needs to be re-sent and received on every change with LSP IS implied.#2019-11-0412:34dominicmEditors can implement the incremental part based on their buffer data structures to provide instant highlighting#2019-11-0412:34dominicmThe key thing here is that most toolchains aren't incremental by default.#2019-11-0412:37borkdude@dominicm LSP can send incremental changes#2019-11-0412:38dominicmI think that the implied problem is that most compilers aren't capable of handling incremental changes. Maybe they are stateless, or simply not designed that way because it isn't useful for their language.#2019-11-0412:38borkdudeit's definitely harder. kondo doesn't support it 😉#2019-11-0412:39borkdudekondo does try to stay within double digits latency though for single files#2019-11-0412:39borkdudeif the linter becomes too slow that's also feedback: split up your file in multiple namespaces 😛#2019-11-0412:45dominicmSometimes there's no real logical way to do that.#2019-11-0412:46dominicmE.g. A model layer for a graph database. You can't split by entity, because your queries operate across many of them.#2019-11-0412:50whiloincremental compilation is a very interesting research field#2019-11-0412:56borkdude@dominicm it's kind of a similar problem that clj-kondo has I think. I do that by passing main functions as arguments to sub-functions. it's a bit of a hack maybe. clojure.core does it with in-ns I think#2019-11-0412:57borkdude(I also tried in-ns briefly, but it's less linter-friendly and also it gave weird problems with graalvm / AOT)#2019-11-0412:59borkdudealso multi-methods may help there#2019-11-0413:09dominicmI don't understand at all, sorry#2019-11-0413:10borkdudeSplitting in multiple files can be achieved with multi-methods, passing functions around as arguments or using in-ns#2019-11-0413:11borkdudeunless I don't understand the problem you described, then I'm sorry 😉#2019-11-0414:01dominicmOh, I just meant that it is sometimes unclear in which dimension to slice up a namespace.#2019-11-0415:02souenzzo@borkdude how do I find all (:require [...]) in my src/main ?#2019-11-0415:12borkdude@souenzzo You mean all referred namespaces? What is the background of your question?#2019-11-0415:18souenzzoI want to programmatic access all :requires in my project I will use it to create assertions like datomic.api should always be aliased as d or do not use refer inside my test suite#2019-11-0415:22borkdude@souenzzo you might like this new feature: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#alias-consistency#2019-11-0415:30borkdudebtw @dominicm I think you asked for this feature once, it's now released#2019-11-0415:30dominicmOh cool!#2019-11-0415:31dominicmHmm. I wanted the config in that situation to be generated from the project.#2019-11-0415:34borkdudeLet me rephrase my previous comment. You might be able to use the analysis data to generate a config. It's hard to infer it while linting, since there can be multiple competing aliases and it also depends on how many files you are linting, so it wasn't a clear cut thing to do#2019-11-0415:39borkdudeAlso the set of namespaces that you want to force a consistent alias for, might not contain every single namespace#2019-11-0417:11souenzzocool thing https://gist.github.com/souenzzo/5a15947ce3449a2a084d7b81d9cb1efd helped me clean up unused dependencies in a project. the output is a hint. Dynamic things like io.pedestal/pedestal.jetty may be wrongly reported.#2019-11-0417:15souenzzo.class things like datomic-pro also wrongly reported but I think that it can be handled#2019-11-0417:16dominicmOh, that's awesome#2019-11-0417:27souenzzodeps from project that aren't used (remove deps-from-requires deps-from-project) deps from requires that arent explicit dependencies (this one is nice as a linter!) (remove deps-from-project deps-from-requires)#2019-11-0417:27borkdudecan you give an example of the latter?#2019-11-0418:15souenzzohttps://gist.github.com/souenzzo/6644f53a8e4c75b95303b07c09af942b#2019-11-0418:15souenzzo@borkdude#2019-11-0418:16borkdudeaaah, you are parsing project.clj#2019-11-0418:17borkdudethere's also one other check which @dominicm has suggested: when you use a qualified var without a require you should get a warning#2019-11-0418:17borkdude(if I remember correctly)#2019-11-0418:17borkdudee.g. (ns foo) (clojure.string/trim ...)#2019-11-0415:22borkdudeand for doing stuff manually, you can use https://github.com/borkdude/clj-kondo/blob/master/analysis/README.md#2019-11-0415:24souenzzo
(kondo/run! {:lint ["src/main"]
             :config {:output {:analysis true}}})
Nice 🙂
#2019-11-0415:23borkdude"do not use refer" isn't included in the analysis data, but it could be an option for the alias-consistency linter maybe#2019-11-0415:23borkdudemaybe that data could also be added to the analysis data#2019-11-0415:24borkdudethe relevant data is now in :namespace-usages#2019-11-0509:58borkdudeDatalog syntax checking is now on master#2019-11-0610:42borkdudeclj-kondo was featured on the CLJS podcast: https://clojurescriptpodcast.com/#2019-11-0614:34eraserhdHey, I just installed clj-kondo, and it is really nice! So, thanks! I use a rando editor (Kakoune), and it was about three lines of config.#2019-11-0614:35eraserhdPart of me appreciating it is this mode of editor integration, which I shall call "Just a Program".#2019-11-0614:36borkdudesounds good! PR welcome here if you want to add editor integration documentation: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#2019-11-0614:37eraserhdI have made myself a note to do so.#2019-11-0614:41borkdudeThanks!#2019-11-0618:56borkdudehas anyone used clj-kondo on macOS catalina?#2019-11-0619:08delaguardoHappily using it since early beta)#2019-11-0619:08delaguardoBeta of Catalina of course#2019-11-0619:08borkdudedid you have to set some security flags to use the clj-kondo binary?#2019-11-0619:09borkdudethere's a discussion about this going on in #graalvm#2019-11-0619:40viestididn't need flagging myself#2019-11-0620:13eraserhdwrt #515 (warn about missing require when using a known namespace), what exactly prevents warning about aliases?#2019-11-0620:14eraserhdit's not a fundamental problem, right?#2019-11-0620:15borkdude@eraserhd can you give an explicit example?#2019-11-0620:19borkdudeI don't understand what you mean with "warning about aliases"#2019-11-0620:20eraserhdif I type str/replace, for example, but don't have a str alias in my ns.#2019-11-0620:23borkdudethat is a fundamental problem, because str could be 1) a fully named namespace, 2) a Java class#2019-11-0620:24borkdudethe only way to lint this is using explicitly configuration, it cannot be detected automatically#2019-11-0620:26eraserhdHmm...#2019-11-0620:27eraserhdOK, so that becomes more complicated. Either it's a class in java.lang, or it's imported, or there's a defrecord or deftype for it in the namespace, or it's a warning?#2019-11-0620:28eraserhdIn terms of configuration, I, personally, would be happy to assume anything starting with a lower case letter is not a Java class.#2019-11-0620:29borkdudegoog in CLJS is another example#2019-11-0620:32eraserhdthis seems like a fixed number of clojure-flavor related exceptions, e.g. goog/ and js/ in cljs is like System/ in clj.#2019-11-0620:34eraserhdhmm, but ok, it's not so simple#2019-11-0620:34eraserhdI wonder how often this shows up in the wild?#2019-11-0620:35borkdudeThere as an issue about this which @dominicm linked recently. Let me try to find it...#2019-11-0620:35borkdudeThis lead to the issue #515#2019-11-0620:36eraserhdYeah, I was getting to asking whether aliases should be on #515 or a separate issue, but it might be neither.#2019-11-0620:39borkdude@dominicm do you maybe remember which issue that was?#2019-11-0620:43dominicmhttps://github.com/borkdude/clj-kondo/issues/339#2019-11-0620:43borkdudeah that's it, thanks#2019-11-0620:43borkdude@eraserhd Feel free to have a look at this. We can reconsider this issue at all times.#2019-11-0620:46eraserhdok. This is closely related to something I've been meaning to do for a while.#2019-11-0620:46eraserhdSo, I might actually look at it.#2019-11-0620:48borkdudeIt's fairly easy to warn when foo is not a required namespace (alias) or imported class. Then we'd have t exclude known things like goog. Clj-kondo already have a list of all the by default available classes, so that's not a problem anymore either. So considering the progress of the last few months, maybe it's actually more feasible now...#2019-11-0620:49borkdudeThe only thing that should be very well researched is false positives#2019-11-0620:51borkdudeI've re-opened the issue and put in the "hammock time" column on the project board#2019-11-0620:51eraserhdI was thinking something like linting 500 big clojure projects and seeing what shakes out.#2019-11-0620:51borkduderight#2019-11-0620:51borkdudeso the warning would be something like "missing require or import"?#2019-11-0620:52eraserhdyeah#2019-11-0620:54eraserhdThis goes beyond clj-kondo, probably, but a thing that's been on my to-do list for years is a thing that updates ones namespace as one types. Aliases are (or should) be used somewhat consistently in a project, so an analyzer could know what to do. I had this for C++ includes a long time ago, and it worked well.#2019-11-0620:55borkdude> Aliases are (or should) be used somewhat consistently in a project There's actually a linter for this now#2019-11-0620:55eraserhdIn kondo?#2019-11-0620:56borkdudeYes: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#alias-consistency#2019-11-0620:56borkdudeYou can generate the initial config using the analysis export which contains all the aliases: https://github.com/borkdude/clj-kondo/tree/master/analysis#2019-11-0620:56eraserhdAhh, nice#2019-11-0620:59borkdudeMaybe it could be useful to add the script which generates this config to the analysis examples. Worth a PR if anyone feels like it#2019-11-0701:59whilobtw. i have also had another fun static analysis project some time ago: https://github.com/whilo/beichte/. i am not sure how important verified functional purity is to users. it would have to be triggered by metadata, i guess. e.g. putting a purity flag on all defns.#2019-11-0709:33coltnzis it just me or does the clj-kondo annotations not work with cursive anymore. I see the warnings in the log "warning: redundant let" but nothing on the code#2019-11-0709:34coltnzon intellij 2019.2.4 and cursive eap8#2019-11-0709:36borkdudeI'm not in control of any changes to IntelliJ but I'm not aware of any changes to clj-kondo which should break existing editor integration#2019-11-0709:38borkdude@coltnz you can try older versions of clj-kondo or older versions of intellij/cursive to be sure#2019-11-0709:40coltnzah ive found it, filewatchers got somehow disabled in inspections listing#2019-11-0709:40coltnzthx for kondo its great#2019-11-0712:49delaguardowrote simple github action to annotate diffs with findings from clj-kondo: https://github.com/DeLaGuardo/clojure-lint-action#2019-11-0712:50borkdude@delaguardo my mind explodes!#2019-11-0712:57delaguardothis is docker-based action atm. So you can not use build tools to calculate classpath for linting. But I will switch it to the hosted solution in the next release.#2019-11-0712:58delaguardoalso I’m really appreciate any kind of feedback)#2019-11-0712:58borkdudeI'll mention this in the release notes of the next release#2019-11-0713:06borkdude@delaguardo if it's easier in any way, you can also use the clj-kondo uberjar from github and run it using java#2019-11-0713:06borkdude(I don't see how that is easier than downloading the binary, but the option is there)#2019-11-0713:07borkdudeOh, running the uberjar also makes it work for Windows builds I guess#2019-11-0713:07borkdudeor if it's easier, you can just write a tools.deps/clojure script while using clj-kondo as a lib and invoke it that way#2019-11-0713:09delaguardobinary or uberjar (I’m more on that approach, because it should work everywhere) a bit easier and also makes github tools caching possible#2019-11-0714:35borkdude@delaguardo https://twitter.com/ordnungswprog/status/1192450191871356929
#2019-11-0716:03delaguardoI did not even knew that issues might be disabled) And this issue is fixed by the way#2019-11-0716:05borkdudeI added a comment to the issue.#2019-11-0716:08borkdude@delaguardo STDERR should be ignored for JSON parsing. It only is used to print exceptions and such.#2019-11-0716:11delaguardoThanks, I’m sure it is ignored. And only used for logging when everything goes bad.#2019-11-0716:12borkdudeoh of course, I misread 🙂#2019-11-0716:12borkdudethanks#2019-11-0716:12borkduderemoved my comment#2019-11-0716:14delaguardoanyway - thanks for noticing)#2019-11-0715:21lreadcool!#2019-11-0716:47borkdudemagic: https://github.com/borkdude/clj-kondo/commit/a6da732a46891fa1502d83d2c9f5c8305d8218f5#annotation_7693137676931376#2019-11-0718:37zaneOh my god.#2019-11-0718:39zaneThis is so incredibly cool, @delaguardo.#2019-11-0718:39zaneMaking a note to try to get this running on our projects.#2019-11-0718:49borkdude@U050CT4HR I added it this way: https://github.com/borkdude/clj-kondo/commit/f84eedf9599634beece1660347a0de38c0166d88#2019-11-0721:26sogaiulol, just finished listening to the clojurescript podcast for clj-kondo -- some of the content is already somewhat out-of-date because of the speed of dev 🙂#2019-11-0721:29sogaiuspecifically, snap support discontinued, potemkin import-vars support done(?), atom editor support, and some type-checking at least have happened since...#2019-11-0721:35borkdudehaha, I can't even remember what features I've mentioned back then. it was recorded in August#2019-11-0814:06borkdudeclj-kondo 2019.11.07 Datalog linting and more! https://github.com/borkdude/clj-kondo/releases/tag/v2019.11.07#2019-11-0814:24borkdudeAlso check out this interesting blog post: https://lambdaforge.io/2019/11/08/clj-kondo-datalog-support.html#2019-11-0816:35sogaiuthat's quite an interesting article -- it's going to take a bit to digest well 🙂 thanks for mentioning it! on a related note, have you checked out clindex (https://github.com/jpmonettas/clindex)? it was mentioned in the article and i saw it was announced recently.#2019-11-0816:38borkdudeyes I think I attended the author of this article about it 🙂#2019-11-0816:42sogaiuah nice!#2019-11-0816:45borkdudeI spotted it on Reddit#2019-11-0816:57sogaiusame 🙂 was thinking whether it might be used to generate tags/TAGS files -- and thereby obsolete what i'm working on 🙂 haven't had much luck reaching the author though he seems to be on slack.#2019-11-0816:59borkdudein the beginning of kondo I have considered using a triplestore like datahike as well, but I never got it to work#2019-11-0816:59borkdudewith graalvm I mean#2019-11-0817:00borkdudeand I think it would be less performant after all than manually storing information in a bunch of maps#2019-11-0817:01sogaiuit does seem possible that it wouldn't be performant enough for real-time query -- but i was thinking it might be used to generate tags/TAGS so the performance wouldn't be a problem#2019-11-0817:01borkdudeI have an example of a babashka script here btw which pulls the clj-kondo analysis into a sqlite database: https://github.com/borkdude/babashka/blob/master/examples/sqlite.clj#2019-11-0817:01sogaiuthanks -- i was going for the "works in many editors" angle initially#2019-11-0817:02sogaiuthere is the tree-sitter thing too to consider#2019-11-0819:00dominicmThat's really cool#2019-11-0820:34sogaiui tried the sqlite.clj script -- it seemed to work fine when passed "src", but something didn't enjoy being passed clj -Spath:
$ bb ~/src/babashka/examples/sqlite.clj `clj -Spath`
clojure.lang.ExceptionInfo: Cannot run program "sqlite3": error=7, Argument list too long [at line 16, column 3]
{:type :sci/error, :row 16, :col 3, :message "Cannot run program \"sqlite3\": error=7, Argument list too long [at line 16, column 3]"}
 at sci.impl.utils$rethrow_with_location_of_node.invokeStatic (utils.cljc:62)
...
#2019-11-0820:50borkdudemaybe try it dependency by dependency?#2019-11-0820:51borkdudeI guess the sqlite binary doesn't like the long argument for some reason#2019-11-0821:26lread@sogaiu I'm guessing you have already seen this: https://stackoverflow.com/questions/51710864/usr-bin-sqlite3-argument-list-too-long#2019-11-0821:32sogaiu@lee no i hadn't -- thanks!#2019-11-1010:35johanwirenHow do I make this not give an arity error from clj-kondo? Tried with the config :lint-as to no effect. (Updated sample below)#2019-11-1010:38johanwiren#2019-11-1010:42borkdudeI can check tonight, afk now#2019-11-1010:46johanwirenCool, thanks.#2019-11-1015:49borkdude@johan528 Your example gives:
$ clj-kondo --lint /tmp/foo.clj
linting took 11ms, errors: 0, warnings: 0
on my machine. I did have to remove a couple of weird Unicode characters though.
#2019-11-1015:50borkdudeThis is the version I ended up using:
(ns foo
  {:clj-kondo/config {:lint-as {foo/__ clojure.core/->}}})

(defmacro __
  [& body]
  `(-> :inject 
#2019-11-1108:01johanwirenI created a PR with a reproducible test case.#2019-11-1108:05johanwirenhttps://github.com/borkdude/clj-kondo/pull/601#2019-11-1108:45borkdudeThanks#2019-11-1108:48borkdudeMade an issue for it here: https://github.com/borkdude/clj-kondo/issues/602#2019-11-1110:59borkdude@johan528 It turned out to be a quoting issue: https://github.com/borkdude/clj-kondo/issues/602#2019-11-1110:59borkdudeThat's quite confusing and happened to me too more than once.#2019-11-1111:00borkdudeThe namespace local config is mostly for testing, it doesn't support all the options from the normal config. So it's better to put it in .clj-kondo/config.edn anyway#2019-11-1111:11johanwirenCool, missed about that quote. However, this exposes the underlying problem, that the custom macro injects the first form, giving:
(defmacro injecting-thread-first
  [& body]
  `(-> :inject 
Which is still valid and should (preferrably) be treated as a ->
#2019-11-1111:13johanwirenThe reason behind this weird macro is that I am writing a custom version of Ogre's macro (https://github.com/clojurewerkz/ogre/blob/master/src/clojure/clojurewerkz/ogre/anon.clj#L12)#2019-11-1111:13borkdudewell, lint-as lints a macro literally as ->, not as -> + something else#2019-11-1111:14borkdudeI think you might just want to exclude linting for this macro. {:linters {:unresolved-symbol {:exclude [(your.macros/__)]}}}#2019-11-1111:15borkdudeand {:linters {:invalid-arity {:skip-args [your.macros/__]}}}#2019-11-1111:16borkdudeThanks for uncovering a bug regarding metadata though 🙂#2019-11-1111:18johanwirenAh, yes I see now. lint-as will not help me. Going for disabling linting for that one.#2019-11-1111:19johanwirenThanks for your help and very helpful tool!#2019-11-1111:20borkdudeThank you too. It's really helpful when users report errors instead of just ignoring them, it makes the quality of the linter better every time.#2019-11-1117:38dharriganhey @borkdude, thanks for the name drop on the cljs podcast re: clj-kondo 🙂#2019-11-1117:39dharriganit's no effort 🙂#2019-11-1118:14borkdudethanks anyway 😉#2019-11-1209:49borkdudeAnyone wants to help debug a problem with IntelliJ LSP support? https://github.com/gtache/intellij-lsp/issues/118#2019-11-1223:37fiddlerwoaroofI came across something that should probably be caught by a linter:
(defn foo [{:as bar}] ...)
should just be
(defn foo [bar])
#2019-11-1223:37fiddlerwoaroofmaybe?#2019-11-1314:41souenzzo(fn [& {:as opts}]) isn't the same of (fn [& opts])#2019-11-1314:50borkdude@fiddlerwoaroof Can be implemented, but probably low priority since it's not wrong and doesn't cost you any performance if you this.#2019-11-1316:31fiddlerwoaroof@borkdude makes sense, I thought it was an interesting case, though, because it usually comes up for me after I've eliminated all the unused bindings from destructuring. #2019-11-1316:35borkdudelow priority doesn't mean "won't implement", you're still welcome to create an issue#2019-11-1316:35borkdudeand if you want to do a PR yourself, it's more likely to get in sooner#2019-11-1318:08eraserhdI've been puzzling over a quirk in my workflow that affects clj-kondo, among other things, and I wonder what to do about it...#2019-11-1318:09eraserhdBasically I'm moving to always have my editor in ~/src, one level above my projects, to lower the barrier to project-switching and make some other things work.#2019-11-1318:09eraserhdThis means that a projects' .clj-kondo/config.edn isn't available by my editor's lint wrapper.#2019-11-1318:11eraserhdI can probably patch my editor's lint script. Hmm, I think that's actually the right thing to do.#2019-11-1318:13eraserhdwell then, carry on :)#2019-11-1318:17borkdude@eraserhd One thing I've been thinking about when linting a single file (which is what you do with editor integration) is search down from the path of the linted file instead of the cwd#2019-11-1318:19borkdudeso when you lint /tmp/foo/bar/baz.clj and your cwd is /tmp/foo but your .clj-kondo is in /tmp/foo/bar, it would still work#2019-11-1318:21eraserhdoh neat. That would solve my problem, and since I would otherwise write a wrapper, I might as well make a PR for that.#2019-11-1318:21borkdudeyes please 🙂#2019-11-1318:22borkdudethat will also solve the problem in VSCode when you edit an "unrelated to the current workspace/dir" clojure file (not sure how common that is, cc @pez)#2019-11-1319:59sogaiuthis sounds similar to the issue i was experiencing with running clj-kondo not from the project directory as root -- clj-kondo resolves paths based on user.dir, at least i think it used to#2019-11-1320:01sogaiuin my indexing program i resolved this by only handing absolute paths to clj-kondo's --lint#2019-11-1320:02borkdudethat's a different problem though#2019-11-1320:02borkdudethis problem has to do with resolving the location of the .clj-kondo directory#2019-11-1320:03sogaiuok#2019-11-1320:17pezWould it still find a .clj-kondo in /tmp/foo? And what does it do if there is a .clj-kondo in both locations?#2019-11-1320:18borkdudethe cwd would basically become /tmp/foo effectively#2019-11-1320:19pezI don’t know about others, but i certainly quite often open up a clj file from somewhere random even when working with a project.#2019-11-1320:21borkdudeyeah, but that file probably doesn't have to be saved to the cache of your project, it's just fiddling around or looking something up quickly#2019-11-1320:22pezIndeed.#2019-11-1403:12eraserhdSo, if there is more than one file, should we start searching at the lowest common ancestor?#2019-11-1403:23eraserhdAlternately: 2) only use first file/directory, 3) find config for each file (arguments, really) indendently#2019-11-1407:44borkdude@eraserhd I’m currently thinking that we should only implement this when linting a single file or directory#2019-11-1407:45borkdudeSince this is probably only useful for editors (so maybe not even when linting a single dir)#2019-11-1407:46borkdudeI think Emacs and IntelliJ already do this #2019-11-1407:47borkdudeThey set cwd to the currently edited file #2019-11-1600:45bringeHello. I have a quick question: Does clj-kondo know how to handle function args in var metadata?#2019-11-1600:45bringeIt appears not, but maybe I'm missing something#2019-11-1608:20borkdude@brandon.ringe This is fixed on master. Will be released soon. https://github.com/borkdude/clj-kondo/issues/597#2019-11-1617:23bringeAwesome! Thanks#2019-11-1612:06dominicmIf I have a unpopular library that introduces a with- macro, can I annotate it somehow so that kondo users don't need to add it to their lint configuration? Maybe something picked up as part of the full analysis#2019-11-1612:39borkdude@dominicm I have been thinking about this as part of these issues: https://github.com/borkdude/clj-kondo/issues/253 https://github.com/borkdude/clj-kondo/issues/559 For #559 I've come to the conclusion for now that it would be most flexible to add a README page for third party library configs where library maintainers can PR their configs. https://github.com/borkdude/clj-kondo/issues/559#issuecomment-551949256 But #253 could help automate this and use rewrite-clj(c) (proper, not my fork) to include it in the config.edn#2019-11-1612:46borkdudeAlso, you can include the kondo config in the README of your lib#2019-11-1614:49sogaiuis there already support for more than one config to be merged? sort of like how for deps, ~/.clojure/deps.edn "merges" w/ a project's deps.edn#2019-11-1615:04sogaiui guess 5 under design principles suggests that there is no at-run-time merging. may be the external tool being considered could do this kind of thing?#2019-11-1615:17borkdude@sogaiu Currently there is .clj-kondo/config.edn and the --config argument that are merged#2019-11-1615:17borkdudeand the ns-local config via metadata#2019-11-1615:17borkdudeand also the built-in config#2019-11-1615:19borkdudeit's by design that no multiple configs are merged from multiple .clj-kondo directories, so people store a complete configuration in a project#2019-11-1616:13sogaiusupposing that library authors provide a config with their library, is it expected for users to have to manually merge this with their local configuration (for which the 3rd party library is a dependency)?#2019-11-1616:18borkdudethe idea of the helper tool is that it can do that for you using rewrite-clj(c)#2019-11-1616:20sogaiuah, so a user won't have to manually piece together 2 (or more?) existing config files?#2019-11-1616:21borkdudeyeah#2019-11-1616:22borkdudethe reason I want it to be another tool is that it can have more dependencies and also work in CLJS, so it can be hooked up with editor tooling#2019-11-1616:22borkdudeI'm not entirely sure about this all#2019-11-1616:22sogaiuduckie#2019-11-1616:23borkdudewhy is there no icon for :hammock:#2019-11-1616:23sogaiuyes, exactly#2019-11-1616:23borkdude@lee, we need your help ^#2019-11-1616:34lreadha! just a parenthesis on its back, no?#2019-11-1619:59Filipe Silvais there a super obvious configuration item to lint devcards?#2019-11-1619:59Filipe Silva#2019-11-1620:00Filipe SilvaI imagine the devcards macros probably have the same shape as something else and that I could use :lint-as, but I don't know what other thing is...#2019-11-1620:02borkdudeprobably clojure.core/def?#2019-11-1620:03Filipe Silvamaybe, I'll try that for now#2019-11-1620:03Filipe Silvathank you#2019-11-1620:03Filipe Silvaif I use the vscode extension, I should still put the config in .clj-kondo/config.edn right?#2019-11-1620:03Filipe SilvaI notice cache doesn't seem to be there#2019-11-1620:05borkdudedoes your .clj-kondo/config.edn live in the root of your opened folder?#2019-11-1620:05borkdudethe cache is only populated when you have a .clj-kondo directory#2019-11-1620:06Filipe Silvaah yes, I didn't have it before#2019-11-1620:06Filipe Silvaso now that I made it, it shows up there#2019-11-1719:09lreadso I was thinking about that hammock icon...#2019-11-1719:09lreaddoes that come across? hard to make itty bitty things look good!#2019-11-1719:13borkdudeis that a moon in the sky?#2019-11-1719:14lreada parenthesis moon, yes#2019-11-1719:15borkdudeI think without the moon it would be clearer, since it doesn't really convey the meaning of a hammock?#2019-11-1719:15sogaiui think i understood it partly because i had expectations#2019-11-1719:15lreadcould you see hammock and person?#2019-11-1719:15borkdudewell, the moon drew my attention, so it took me a while#2019-11-1719:15lread#2019-11-1719:16lreadlooks nice bigger, eh?#2019-11-1719:16sogaiuahhhh, the multi-color part gets lost when shrunk#2019-11-1719:16lreadalas, yes#2019-11-1719:17sogaiupossibly one drawback to the moon is that it sometimes suggests sleeping#2019-11-1719:17lreadthe moon was kind of conveying sleeping on it... and filling an empty space.#2019-11-1719:17sogaiulol, i see -- i just remembered what rh said about pretending to be sleeping 🙂#2019-11-1719:18sogaiubut you're right, part of the process may occur while sleeping#2019-11-1719:18borkdudehammock isn't necessarily for sleeping, just relaxing#2019-11-1719:18lreadI think the moon has been down-voted 😄#2019-11-1719:18sogaiuif it were to stay, i'd like it yellow 🙂#2019-11-1719:18borkdudeI agree, yellow is clearer#2019-11-1719:18sogaiuhammock made small seems quite challenging#2019-11-1719:19borkdudeyou can also make it a yellow ball, which can be seen as a moon or sun#2019-11-1719:19sogaiuooo, sneaky#2019-11-1719:19sogaiui like the angle of suggesting being outside#2019-11-1719:20borkdudeyeah#2019-11-1719:20borkdudemaybe a cloud which also suggest thinking about it?#2019-11-1719:20sogaiui like that ambiguity#2019-11-1719:20lreadI think hammock without moon works better too#2019-11-1719:21sogaiu(does that encourage the use of a dark theme for one's slack ui?)#2019-11-1719:21lreadthe little person is blue to show in both dark and light themes.#2019-11-1719:22sogaiuuse of blue and green seems appropriate 🙂#2019-11-1719:23sogaiuthe dark theme remark was intended to be linked to the idea of the cloud -- wasn't sure how well it would show up#2019-11-1719:23lreadI think I'm learning to keep things to minimum for icons. I'll just leave it as hammock and person for now. hammock#2019-11-1719:23sogaiusounds good to me#2019-11-1719:23lread#2019-11-1719:24borkdudeworks for me!#2019-11-1719:24sogaiuthe thing i learned watching someone make icons over some years was -- compose existing simple pieces#2019-11-1719:25lreadhow fantastic the hammock looks will be left a secret. simple_smile#2019-11-1719:25lreadyeah that's a good thing to remember @UG1C3AD5Z, thanks.#2019-11-1814:58tatutI was working on a fix for https://github.com/borkdude/clj-kondo/issues/496, but unfortunately I haven't found the time to do open source work lately... if anyone needs that feature urgently, feel free to work on it as well#2019-11-1815:04borkdude@tatut want me to unassign it?#2019-11-1815:04tatutsure, thanks#2019-11-1816:11borkdudeDone#2019-11-1907:43jaihindhreddyDoes clj-kondo warn when some know lazy construct is being created but not forced to be realized in the lexical scope of with-redefs?#2019-11-1907:58jaihindhreddyAfter more thinking, doing so would require analysis through dynamic scopes, because things outside of core can both create lazy stuff and force it to be realized (without telling us so). So maybe it is out of scope for clj-kondo. Maybe a job for a more involved static analysis tool.#2019-11-1908:30borkdude@jaihindhreddy Same trouble with try, with-open and binding#2019-11-1908:32borkdudeClj-kondo could in theory warn about (try (map ...)) because it can know about a set of functions that are lazy like map. Maybe eastwood already has this? I'll ask in their channel.#2019-11-1908:34borkdudeAh great, it's in var-info.edn already: https://github.com/jonase/eastwood/blob/fa22247fa976d03fd37cdfbb4554d26e61b3842b/resource/var-info.edn#L373#2019-11-1908:38borkdude@jaihindhreddy Feel free to post more examples here: https://github.com/borkdude/clj-kondo/issues/614#2019-11-1911:50worrelsik@borkdude Sorry, I had to fix another error I made (def i.s.o. defn) first... From the Clojure for the Brave and True book, chapter 6:
(ns the-divine-cheese-code.core
  (:gen-class))
(require 'the-divine-cheese-code.visualization.svg)
(refer 'the-divine-cheese-code.visualization.svg)

(def heists [{:location "Cologne, Germany"
              :cheese-name "Archbishop Hildebold's Cheese Pretzel"
              :lat 50.95
              :lng 6.97}
             {:location "Zurich, Switzerland"
              :cheese-name "The Standard Emmental"
              :lat 47.37
              :lng 8.55}
             {:location "Marseille, France"
              :cheese-name "Le Fromage de Cosquer"
              :lat 43.30
              :lng 5.37}
             {:location "Zurich, Switzerland"
              :cheese-name "The Lesser Emmental"
              :lat 47.37
              :lng 8.55}
             {:location "Vatican City"
              :cheese-name "The Cheese of Turin"
              :lat 41.90
              :lng 12.45}])

(defn -main
  [& args]
  (println (points heists)))
clj-kondo complains about 'points' in the prinln form. lein run gives expected output, though.
#2019-11-1911:51worrelsikand the corresponding namespace:
(ns the-divine-cheese-code.visualization.svg)

(defn latlng->point
  "Convert lat/lng map to comma-separated string"
  [latlng]
  (str (:lat latlng) "," (:lng latlng)))

(defn points
  [locations]
  (clojure.string/join " " (map latlng->point locations)))
#2019-11-1911:52borkdude@roger429 clj-kondo doesn't support (refer ...). To be honest I've never used this myself in 10 years of Clojure. Just use (require '[the-divine... :refer [points]])#2019-11-1911:53borkdudeSo maybe I should add support for it, I'll make a ticket for it#2019-11-1911:55borkdude@roger429 https://github.com/borkdude/clj-kondo/issues/615#2019-11-1911:59worrelsik
(require ['the-divine-cheese-code.visualization.svg :refer [points]])
still has squiggles under points.
#2019-11-1912:00borkdudeyou need to put the quote in front of the vector#2019-11-1912:00worrelsikOooh#2019-11-1912:01worrelsikThank you! I'm not the eagle-eyed reader at the moment that Daniel Higginbotham assumes his readers to be:blush:#2019-11-1912:09borkdudeno problem 🙂#2019-11-1918:52pezI almost recruited a Calva user the other day. He liked the help I got with unused and misused stuff. I’m pretty sure he was ready to install VS Code. Then I told him it was clj-kondo doing the magic and that he could use it in Emacs as well. 😃#2019-11-1919:09sogaiuvery much enjoying the ability to use clj-kondo in various editors :thumbsup: am a big fan of tooling that can be shared in a variety of environments.#2019-11-2010:15pithylessHas anyone got clj-kondo working with better-cond? It'd be nice to get better support for it's non-standard use of :let [..], etc. For now, I'm just using:
{:unresolved-symbol {:exclude [(better-cond.core/cond)]}}
#2019-11-2010:19borkdude@pithyless I'm not familiar with better-cond. Can you post some examples to give me an idea?#2019-11-2010:21pithylessI probably can't do it more justice than this example from the README: https://github.com/Engelberg/better-cond#usage#2019-11-2010:23pithylessBut for purpose of clj-kondo, I think this is the crux of it:
(b/cond
  :let [num 42]
  (= num 42) :life)
#2019-11-2010:24pithylesskondo is highlighting the num in let as unresolved#2019-11-2010:27borkdudeprobably the config you're using is best for now. I don't see enough similarity with other built-in macros#2019-11-2010:34pithylessYeah, I think you would need to be able to traverse and evaluate (psuedocode):
[(:symbol better-cond.core/cond) [:* (:pairs [:keyword :let] [:eval-like clojure.core/let-bindings])]]
#2019-11-2014:56eelkeHey! Love clj-kondo. Currently adding it to CI. One question: can the program ignore all warnings and only fail if there are errors?#2019-11-2014:58eelkeOr is it only able to suppress warnings on specific symbols?#2019-11-2015:31delaguardoyou can ignore exit codes lower than 3 in CI to fail only in case of error#2019-11-2016:29borkdude@eelke that's right. https://github.com/borkdude/clj-kondo#exit-codes#2019-11-2016:30borkdudealso each linter's level is configurable, so if you want to disable one kind of linter, you can set its level to :off in the configuration#2019-11-2016:30borkdudeor to :warning, :error or :info#2019-11-2101:52sogaiuone step closer to windows support command prompt:
echo (inc) | .\clj-kondo.exe --lint -
powershell:
echo '(inc)' | .\clj-kondo.exe --lint -
#2019-11-2102:01sogaiu@borkdude it appears the following is sufficient for getting IncludeResources to work on windows:
call %GRAALVM_HOME%\bin\native-image.cmd ^
  -jar target/clj-kondo-%CLJ_KONDO_VERSION%-standalone.jar ^
  "-H:Name=clj-kondo" ^
  -H:+ReportExceptionStackTraces ^
  "-J-Dclojure.spec.skip-macros=true" ^
  "-J-Dclojure.compiler.direct-linking=true" ^
  "-H:IncludeResources=clj_kondo/impl/cache/built_in/.{0,}" ^
  "-H:ReflectionConfigurationFiles=reflection.json" ^
  --initialize-at-build-time  ^
  "-H:Log=registerResource:" ^
  --verbose ^
  --no-fallback ^
  "-J-Xmx3g"
#2019-11-2107:48borkdude@sogaiu nice!#2019-11-2109:22borkdudeExperimental new Windows build: https://ci.appveyor.com/api/buildjobs/oqwh72id7x3q8es2/artifacts/clj-kondo-2019.11.08-SNAPSHOT-windows-amd64.zip. Please give it a shot.#2019-11-2109:31borkdudeFrom what I'm seeing on CI, this looks pretty good#2019-11-2113:52borkdudeI'm happy to have confirmation from @filipematossilva that the .exe works under Windows now!#2019-11-2113:58Filipe Silvaif you add it to the release assets for releases, the npm package will just pick it up#2019-11-2113:59Filipe Silvabtw I haven't been updating the npm package on each of clj-kondo's release... I wanted to automate that, but haven't#2019-11-2113:59borkdudeno worries, I guess people will start asking if they really need it faster than you are doing it#2019-11-2114:00borkdude@marc-omorain maybe there are some Windows users in CircleCI that want to give the clj-kondo.exe a test? Maybe some Calva users, @pez?#2019-11-2114:01Filipe SilvaI should make a github action to do that, check the release version of another repo and run a script with the new version#2019-11-2114:02borkdudeso the npm package is looking for a windows exe and if it's not there it falls back to the jar?#2019-11-2114:04Filipe Silvayeah#2019-11-2114:06Filipe Silvafor npm distributions the 18mb single file might be a problem#2019-11-2114:06Filipe Silvait makes it more likely that the retrieval from the registry will not succeed#2019-11-2114:07Filipe Silvaon some CI envs we see that happening with yarn and large packages#2019-11-2114:07borkdudeI see two potential problems with this script: https://github.com/filipesilva/clj-kondo/blob/e4e48a1f2f1ae01dbc2ea4d362b4f44da579f743/index.js#L22 the entry for windows is not there and the binary is named clj-kondo.exe on Windows (not just clj-kondo)#2019-11-2114:07borkdudefor now let's just leave it like this#2019-11-2114:08borkdudeI'll provide the binary via scoop, and when it gives no further problems, we can migrate it to npm#2019-11-2114:09Filipe Silvahttps://github.com/filipesilva/clj-kondo/blob/master/bin/clj-kondo takes care of the exe bit#2019-11-2114:09Filipe Silvabut yes, there's no url entry for the windows one there#2019-11-2114:17borkdudeah right#2019-11-2114:23Marc O'MorainWe don’t have any Windows developers afaik#2019-11-2114:25borkdudeok#2019-11-2115:41pez@borkdude, just ask for testers in #calva-dev . My experience is that I succeed in recruiting one or two. 😃#2019-11-2119:04borkdudeI or someone else should really make a flow diagram of how text -> code -> analysis -> linting works in clj-kondo. If someone really really feels like this, please yell. Probably http://draw.io is a good tool to use because it's free and thus friendly for OSS.#2019-11-2119:43sogaiuhave interest in participating, but am in the camp of "needing lots of practice drawing". not sure if i can be much help here.#2019-11-2203:15sogaiuthis sort of skips some bits, but here's a draft#2019-11-2210:56borkdude@U04V5V0V4 ^#2019-11-2208:57worrelsik I'm getting this with the windows executable:
PS C:\Users\roger\Downloads\clj-kondo-2019.11.08-SNAPSHOT-windows-amd64> cat .\foo.clj
(def x (def x 1))

PS C:\Users\roger\Downloads\clj-kondo-2019.11.08-SNAPSHOT-windows-amd64> .\clj-kondo.exe --lint .\foo.clj
.\foo.clj:1:1: error: unresolved symbol ??
.\foo.clj:1:12: error: unresolved symbol x
.\foo.clj:1:16: error: unresolved symbol
.\foo.clj:1:18: error: unresolved symbol def
.\foo.clj:1:30: error: unresolved symbol 1
linting took 16ms, errors: 5, warnings: 0
#2019-11-2208:58worrelsikAlthough the very first test worked:
PS C:\Users\roger\Downloads\clj-kondo-2019.11.08-SNAPSHOT-windows-amd64> echo '(def x (def x 1))'| .\clj-kondo.exe --lint -
<stdin>:1:8: warning: inline def
#2019-11-2209:00borkdude@roger429 can you maybe share that file? #2019-11-2209:01worrelsikyou mean the foo.clj?#2019-11-2209:07borkdudeYes#2019-11-2209:08borkdude@sogaiu thanks, good start :-)#2019-11-2209:31borkdude@roger429 I think there might be something wrong with that file? When I lint it locally (thanks for sending it):
$ clj-kondo --lint ~/Downloads/foo.clj
/Users/borkdude/Downloads/foo.clj:1:1: error: unresolved symbol ��
/Users/borkdude/Downloads/foo.clj:1:12: error: unresolved symbol x
/Users/borkdude/Downloads/foo.clj:1:16: error: unresolved symbol
/Users/borkdude/Downloads/foo.clj:1:18: error: unresolved symbol def
/Users/borkdude/Downloads/foo.clj:1:30: error: unresolved symbol 1
linting took 120ms, errors: 5, warnings: 0
#2019-11-2209:31borkdude
$ cat ~/Downloads/foo.clj
��(def x (def x 1))
#2019-11-2209:33borkdudehmm, in Emacs it works fine. It might be the Unix vs Windows line separator issue?#2019-11-2209:38borkdudeThis is what I see in hexl-mode:
fffe 2800 6400 6500 6600 2000 7800 2000  ..(.d.e.f. .x. .                  
#2019-11-2209:38borkdudeSo the first character is fffe which is not a valid Unicode character?#2019-11-2209:41worrelsikVSC shows that file to have an UTF-16LE encoding (little endian?). Probably has to do with the way Powershell pipes the result of echo into the file. I created a file in VSC and it has UTF8 encoding. That file is handled as expected by clj-konde.exe.#2019-11-2209:41borkdudeah#2019-11-2209:41borkdudethanks#2019-11-2209:44worrelsikThe UTF-8 file is 17 bytes; the UTF-16 LE 36 bytes: double the UTF-8 + a BOF marker or some such thingy.#2019-11-2209:46worrelsikDo you have more suggestions for testing on windows?#2019-11-2209:47borkdude@roger429 You could try @marc-omorain's clojure-lint plugin in VSStudio and disabling the clj-kondo plugin. When you have clj-kondo.exe on the path, it should use that I think#2019-11-2209:48worrelsikI'll have a go with that tonight#2019-11-2209:48borkdudealso linting a classpath could be a nice test:
clj-kondo --lint $(lein classpath)
#2019-11-2211:06borkdude@sogaiu feel free to PR your flow diagram including the http://draw.io sources. And feel free to improve it over time#2019-11-2214:43sogaiuok. any specific feedback? e.g. technical inaccuracies or omissions? aesthetic points fine too 🙂#2019-11-2214:45borkdudeI think it's better to discuss in a PR, since Slack gets a little bit all over the place for me#2019-11-2212:32Marc O'MorainI’ve never tried my plugin on Windows - so YMMV. Please do try it though.#2019-11-2212:33borkdudeI wonder if it will recognize the binary correctly... .exe is different from other platform names#2019-11-2212:33borkdudeif clj-kondo was a commercial product, I would buy a windows machine to test 😉#2019-11-2212:33Marc O'MorainWindows has Opinions about binary names. We had fun porting our golang “build agent” at CircleCI to Windows.#2019-11-2212:34Marc O'MorainWe first ran the Linux version of the code on Windows, - we copy the binary into a tmp folder, and invoke it. c:\tmp\build-agent#2019-11-2212:34Marc O'Morainbut that’s won’t execute - you need to name it .exe 😂#2019-11-2212:35Marc O'Morainbut you can invoke the binary without specifying .exe#2019-11-2212:35Marc O'MorainWindows will see if the path that you are invoking has a corresponding .exe or .cmd file, and it runs that.#2019-11-2212:36borkdudethen with a little bit of luck it should already work on Windows I guess#2019-11-2212:36borkdudeI would test this in a Windows VM, but for some reason VirtualBox crashes often on my new Macbook Pro#2019-11-2212:36borkdudeas in: totally crashes the machine, hard reboots it#2019-11-2212:38borkdudeMaybe in Catalina things are better, but I'm also afraid to upgrade to that 😛#2019-11-2212:40Filipe Silvabinary execution on windows is further complicated by the fact that some extensions are only picked up from a given shell#2019-11-2212:40borkdudethere is no global path variable?#2019-11-2212:41Filipe Silvanot that#2019-11-2212:41Filipe Silvait's just that .cmd files won't run without a windows shell#2019-11-2212:41Filipe Silvahttps://github.com/angular/angular-cli/issues/16119#issuecomment-552561958#2019-11-2212:41Filipe Silvahttps://nodejs.org/dist/latest-v10.x/docs/api/child_process.html#child_process_spawning_bat_and_cmd_files_on_windows#2019-11-2212:42Filipe Silvaneither will bat#2019-11-2212:42borkdudeah... hm. maybe that also conflicts with how scoop does things, because it makes these .cmd wrappers?#2019-11-2212:42borkdudewhat a pain#2019-11-2212:42Filipe Silvaso depending on how you try to spawn the process, it might fail to find some executable#2019-11-2212:42Filipe Silvaindeed 🙂#2019-11-2212:44Filipe SilvaI understand the feeling from a maintainers point of view, but from a consumer POV it is also a pain that half the open source software doesn't work on windows#2019-11-2212:44Filipe Silvaeveryone can install linux, but in practice development happens not on linux but on mac#2019-11-2217:52practicalli-johnPlease don't claim your experiences are the same everyone else has. I have done all my professional development work, since 1997, on Linux. Working around Europe I noticed most development machines my colleagues had were a ThinkPad running Linux. I would not presume to tell anyone that there is only one machine that development is done on, as it would make me sound quite arrogant.#2019-11-2218:20Filipe Silvayou know what, I was totally wrong to assume that and should have copped on when I linked the stack overflow survey#2019-11-2218:20Filipe Silvait showed ~50% windows, ~25% osx, ~25% linux#2019-11-2218:21Filipe Silvamy experience was indeed most of my colleagues were on osx and I was always the lone windows#2019-11-2218:21Filipe Silvabut I guess that's mostly a siloed thing, where whole places buy in to one OS or another#2019-11-2218:25practicalli-johnThank you.#2019-11-2212:45Filipe Silvaso it ends up almost being a matter of privilege#2019-11-2212:45Filipe Silvaif you don't work on a mac, you're a second class citizen in the open source world 🙂#2019-11-2212:46Filipe SilvaI don't hear this topic being discussed as much but I think it ended up being yet another mac-related lock-in#2019-11-2212:48Filipe Silvawindows sure could be easier to work on but at the end of the day windows hosts around half the developers#2019-11-2212:48Filipe Silvahttps://insights.stackoverflow.com/survey/2019#technology-_-developers-primary-operating-systems#2019-11-2212:57dharriganI would disagree with that statement development happens not on linux but on a mac#2019-11-2212:58dharriganThat's a very sweeping generalisation. At our place of work, it's 99% linux, with one windows machine.#2019-11-2212:58dharriganThere may be many more people using mac's - but how many of those are using mac's for the adobe range of software, rather than just cutting code.#2019-11-2212:59borkdudeAlso, there's probably a reason why people gravitate towards linux or mac for development. The shell experience has been behind for years in Windows.#2019-11-2213:00dharriganIn regards the stackoverflow survey, 1. it's stackoverflow so inherently biased and 2. what is the error margin? One survey does not make a statement about fact.#2019-11-2213:05dharriganI've never considered myself a second class citizen by using linux (and I also have a few macs) - I would indeed argue with the recent changes that Apple are pushing out to developers with the changes to their OS, life for a developer on mac's is becoming more difficult! I've always found - as a linux user - to be catered for in terms of development - software, documentation, processed, tools - everything I need is available on Linux. I've never had to go scrambling to a Mac to continue working.#2019-11-2215:01sogaiuinterested in seeing what kind of quantified evidence there is for "development happens not on linux but on mac" -- a bit broad perhaps too. in terms of actually making command line tools, my impression has been that stuff gets ported to the mac, but often starts on some other *nix. i wonder if there is some way to comb repository histories for evidence.
#2019-11-2215:02sogaiui've used macos on and off for a while, but for the kinds of things i wanted to do, found i often had to reach for another *nix because what i wanted wasn't available for macos (yet). may be this would make an interesting topic for #off-topic.#2019-11-2218:22Filipe Silva@jr0cket called me out on that as well, and it true: that was an unwarranted generalization based on my experience#2019-11-2218:23Filipe Silvabut to be fair I never argued that Linux users were second class to mac users, I argued that windows users are second class in open source (on the topic above)#2019-11-2218:24practicalli-johnTo err is human, to correct that error is divine 😁#2019-11-2218:28Filipe SilvaI think linux is a first class citizen in open source, because it's the gold standard for where the software should run#2019-11-2218:38sogaiuthanks for pointed out the topic above -- had not digested it 🙂#2019-11-2218:39sogaiustill think it would make for an interesting discussion on #off-topic -- not to mention an interesting study (especially if evidence could be gathered in a semi-automated fashion)#2019-11-2218:45whiloi would argue that closed source operating systems compose way worse with open source development systems. linux is still poor, it is no match to the integration lisp machines had, but at least you can go in and adapt parts, if needed. despite all the open source propaganda from microsoft they still have not open sourced any of their core infrastructure. they just make it convenient enough for people to integrate all the free labor on their platform so that they don't become obsolete#2019-11-2218:46whilothat is the same strategy that apple has used to great success. yet i would never consider running infrastructure on macs, because you have to buy into a giant black box.#2019-11-2218:49whiloi also would like to say that countless open source man years have been put into proving the microsoft model of developing software wrong. that they have adapted does not mean that they are really for open source. the github source code is also not open source for instance, although it would be maybe the most logical thing to do from an open source perspective.#2019-11-2218:51whiloi think times have changed and the terms of this struggle are shifted because of the role of data, but it is important to be aware of who has brought us the open source world and what a pain it was 15 or 20 years ago#2019-11-2316:38borkdudeClj-kondo v2019.11.23: unused imports, a working Windows binary (thank you GraalVM 19.3.0!) and a couple of improvements/bugfixes. https://github.com/borkdude/clj-kondo/releases/tag/v2019.11.23#2019-11-2316:42Filipe Silvaalso released the npm package for that version, with support for the windows binary: https://github.com/filipesilva/clj-kondo#2019-11-2316:43borkdude@filipematossilva Kewl! Did you test it on Windows?#2019-11-2316:44Filipe SilvaI have CI testing it on windows#2019-11-2316:44borkdudebrilliant#2019-11-2316:44borkdudeThanks#2019-11-2316:48borkdude"Run binary with no args" seems a lot faster#2019-11-2318:31Filipe SilvaIndeed :D#2019-11-2316:48borkdudethan the last Windows build, so that looks good#2019-11-2317:36borkdudeIn Windows + VSCode with the @marc-omorain clj-kondo lint plugin installed and the NPM package, I get:#2019-11-2317:37borkdudeIt works fine from the terminal:#2019-11-2317:38borkdudeMaybe it's just a matter of restarting VSCode. I'll try after dinner#2019-11-2317:39Marc O'MorainI’m calling shelljs.which("clj-kondo") to check if it’s on the path.#2019-11-2317:40borkdudedoes VSCode support running this in some JS console?#2019-11-2317:41Marc O'Morain@pez might know. I think you can open the chrome console somehow.#2019-11-2317:43borkdudeWhen I open a terminal in VSCode, clj-kondo is there#2019-11-2317:44borkdudenot sure how I get access to shelljs from the browser console#2019-11-2317:45borkdudeI'll just try in development mode later#2019-11-2318:01pezDefinitely should be tracked down with the extension in dev mode.#2019-11-2319:13borkdudeIt seems TypeScript forbids these debugging hacks...#2019-11-2319:17littlelijust for my curiosity, can you try:
vscode.window['which'] = which;
#2019-11-2319:18borkdudethat also didn't work#2019-11-2322:40Filipe Silvathis looks like just a TS error#2019-11-2322:41Filipe Silvayou should be able to cast the object to any#2019-11-2322:41Filipe Silva(vscode.window as any).which = which#2019-11-2322:45borkdudeah, thanks#2019-11-2319:22borkdudeSeems to magically work in dev mode:#2019-11-2319:25borkdudeSo.. it works in development mode, but not when I install clojure-lint 0.5.0#2019-11-2319:26borkdude@marc-omorain did you release the latest changes to the marketplace?#2019-11-2319:26borkdudeit doesn't appear so#2019-11-2319:27Marc O'Moraini thought i did#2019-11-2319:27Marc O'MorainI don’t know where to admin that 😄#2019-11-2319:27borkdudeThere seem to be two commits after 0.5.0#2019-11-2319:28borkdudeI'll wait for the new release and then I'll give it a try again#2019-11-2319:28Marc O'Morainincoming….#2019-11-2319:35borkdudeI left my VM unattended for a minute:#2019-11-2319:36Marc O'Morain@borkdude https://marketplace.visualstudio.com/items?itemName=marcomorain.clojure-lint 0.6.0 is live#2019-11-2319:40pezThat is Windows for me, @borkdude , waiting for it to update and install and whatever.#2019-11-2319:42borkdudeHard crash again with VirtualBox, machine hard reboots#2019-11-2319:44borkdude@marc-omorain Confirmed it works with 0.6.0:#2019-11-2319:47borkdude> Small update. I've found if I reboot a VM from within Virtualbox it will crash. https://forums.virtualbox.org/viewtopic.php?f=8&amp;t=93739&amp;sid=49d1ab9315fc4d748021c2de56f31742&amp;start=30 Yup, that just happened to me#2019-11-2319:49borkdudeAnyway, happy it works. Thanks Marc!#2019-11-2319:50borkdude@marc-omorain I guess you can remove > At this time, macOS and Linux are supported. Runing GraalVM on Windows has some issues. now#2019-11-2319:50borkdudeIt might be nice to add the marketplace link to the repo#2019-11-2319:56Marc O'MorainGood idea, I’ve done both now, and updated the changelog.#2019-11-2319:56Marc O'Morain0.6.1 incoming#2019-11-2320:00borkdudeThanks 🙂#2019-11-2320:04borkdudeSo now we have 2 package managers for Windows that can install the clj-kondo binary and two VSCode plugins that support clj-kondo linting. Windows people have choices now 🙂#2019-11-2320:05borkdudeI guess it also works with Emacs on Windows now#2019-11-2320:05borkdudealright, thanks a lot everybody who helped testing this#2019-11-2320:43Marc O'Morain> Emacs on Windows shudder#2019-11-2409:16practicalli-johnI used Emacs on Windows (7 and 10) for a year at a bank. It’s not quite as snappy as on Linux but very usable. The biggest challenge was finding an Internet proxy that didn’t require Windows NTLM authentication. Once that was found, it was pretty smooth. I even forgot I was on Windows with Emacs on full screen#2019-11-2321:06borkdudeI actually used Emacs on Windows when I started to learn Clojure#2019-11-2412:42borkdudeIf someone is using the Windows executable or just wants to do a tedious but useful task: https://github.com/borkdude/clj-kondo/issues/233#2019-11-2416:57sogaiui am looking into that issue a bit#2019-11-2416:57sogaiui'm stuck at getting the clj / clojure part working in my windows vm#2019-11-2416:58sogaiuafter installation of clj-on-windows, for an invocation of clojure in clj-kondo's directory i get:
Error: Could not find or load main class clojure.main
Caused by: java.lang.ClassNotFoundException: clojure.main
2019/11/24 08:56:38 open .cpcache/ec67dd60.cp: The system cannot find the path specified.
for reference, the above was pilot error
#2019-11-2416:59borkdudecan you try if leiningen works?#2019-11-2416:59borkdudejust for the sake of debugging#2019-11-2417:02sogaiulein produces the expected help output, and lein test has initiated fetching of deps#2019-11-2417:04sogaiui'm now greeted by test output with lots of things to tweak / fix(?)#2019-11-2417:04borkdudeprogress 🙂#2019-11-2417:04borkdudea lot probably has to do with hardcoded file path separators#2019-11-2417:05borkdudeso "foo/bar" instead of (.getPath`(io/file "foo" "bar"))`#2019-11-2417:05sogaiusure for reference, the output at the bottom is:
Ran 120 tests containing 1105 assertions.
44 failures, 2 errors.
Tests failed.
#2019-11-2417:06borkdudeFile paths are used a lot so that might be expected#2019-11-2417:06sogaiui guess one could take the windows output and make the changes in a non-windows env first#2019-11-2417:07borkdudesure yes, if you can paste that somewhere?#2019-11-2417:07sogaiui'm on it#2019-11-2417:07borkdudeor maybe attach it at the issue as a .zip file#2019-11-2417:09sogaiui just did .txt -- is there a reason to use .zip?#2019-11-2417:10borkdudeno, .txt is fine 🙂#2019-11-2417:17borkdude
actual: .IOException: Cannot run program "rm": CreateProcess error=2, The system cannot find the file specified
#2019-11-2417:17borkdudeyep, that's also a difference 🙂#2019-11-2417:18borkdude
actual: (not (clj-kondo.test-utils/submap? {:file "corpus/defmulti.clj", :row 7, :col 12, :level :error, :message "unresolved symbol greetingx"} {:file "corpus\\defmulti.clj", :row 7, :col 12, :level :error, :message "unresolved symbol greetingx"}))
#2019-11-2417:18borkdudecorpus/defmulti vs corpus\\defmulti yes, that happens a lot#2019-11-2417:19borkdudeI could probably patch assert-submaps to handle that magically for :filename or something, that would already be a quickwin#2019-11-2417:26borkdudeon it#2019-11-2417:34borkdude@sogaiu could you try again with clj-kondo from master?#2019-11-2417:34sogaiuok#2019-11-2417:34borkdudeI expect a few less failures now#2019-11-2417:40sogaiuis this the right commit? 594a0236c81815ad27837507145fbd9215000e9b#2019-11-2417:44sogaiunew results added to issue#2019-11-2417:45borkdudebrb#2019-11-2417:53sogaiudidn't clean first -- trying again#2019-11-2418:04littlelimy summary is slightly different:
Ran 120 tests containing 1105 assertions.
41 failures, 2 errors.
#2019-11-2418:05sogaiuhmm... what shell did you use, btw?#2019-11-2418:08littleli
PS C:\Users\alesn> $PSVersionTable.PSVersion                                                                                                                                                                                     
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      18362  145
#2019-11-2418:10sogaiu
> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      17763  771
#2019-11-2418:10littleliI'll attach output as txt to the issue for comparison#2019-11-2418:11sogaiufwiw, when i do lein test from git bash i get:
Ran 120 tests containing 1113 assertions.
44 failures, 2 errors.
Tests failed.
#2019-11-2418:11sogaiunumber of assertion differs there#2019-11-2418:11sogaiumay be it has access to some things that command prompt and powershell don't#2019-11-2418:12borkdudemade a typo, I should have written :file instead of :filename#2019-11-2418:12borkdudeI will correct, brb#2019-11-2418:22sogaiu@ales.najmann btw, thanks for the clojure scoop bucket 🙂#2019-11-2418:25littleliYou're welcome 🙂 it's actually not such a big deal. Most of the work has been already done before. I just focused a bit more to deliver the experience.#2019-11-2419:00littleliI'm not sure it it is helpful, but there is probably better way to deal with filepaths with java.nio.file.Paths.get("foo/bar.txt") and java.nio.file.Path.normalize() but just swap impl. of normalize-filename is obviously not enough.#2019-11-2419:03borkdudeI made a windows-tests branch. Feel free to re-test there and make PRs, even small ones#2019-11-2419:04borkdudeOne useful one would be to port the script/test script to .bat and hook it up on Appveyor#2019-11-2419:04borkdudeAlso wrote it down here: https://github.com/borkdude/clj-kondo/issues/233#2019-11-2419:07borkdude@ales.najmann normalize-filename just coerces all backward slashes to forward slashes, it's a bit of a hack, but I think it suffices.#2019-11-2419:18sogaiucommand prompt results with windows-test branch:
Ran 120 tests containing 1166 assertions.
9 failures, 3 errors.
Tests failed.
#2019-11-2419:19borkdudebetter#2019-11-2419:19littlelithat's interesting:
Ran 120 tests containing 1166 assertions.
6 failures, 3 errors.
https://gist.github.com/littleli/a7c77530d3b0a9b5544a65bb2a21da29
#2019-11-2419:19littleliwhy we have different results? 🙂#2019-11-2419:20borkdude@ales.najmann I suspect you have the rm and mv commands on the path?#2019-11-2419:20borkdudeor maybe defined aliases for them?#2019-11-2419:21littlelihmm, I have Move-Item and Remove-Item aliases in Powershell, I guess#2019-11-2419:21littleli
PS C:\Users\alesn\Projects\clj-kondo> rm

cmdlet Remove-Item at command pipeline position 1
Supply values for the following parameters:
Path[0]:
PS C:\Users\alesn\Projects\clj-kondo> mv

cmdlet Move-Item at command pipeline position 1
Supply values for the following parameters:
Path[0]:
#2019-11-2419:22borkdudethat's why they work in your case then 🙂#2019-11-2419:23littleliok, but I still se some exceptions regarding these in the output#2019-11-2419:23littleli
ERROR in (import-vars-test) (ProcessBuilder.java:1128)
Uncaught exception, not in assertion.
expected: nil
  actual: .IOException: Cannot run program "mv": ...
#2019-11-2419:23borkdudeoh hm#2019-11-2419:24sogaiufwiw, i added my latest results to the issue#2019-11-2419:27borkdudetrying to hook the tests up here now. installing littleli's clojure scoop:#2019-11-2419:27borkdudehttps://ci.appveyor.com/project/borkdude/clj-kondo/builds/29085056#2019-11-2419:27sogaiurough summary:
ERRORS

run!-test
cache-test
import-vars-test

FAIL

extract-cljs-core-vars-test x3
nested-namespaced-maps-test
redundant-let-test
read-error-test
exclude-clojure-test
inline-def-tes
invalid-arity-test
#2019-11-2419:27borkdudethanks#2019-11-2419:30littleliIn my case:
312:FAIL in (nested-namespaced-maps-test) (main_test.clj:256)
318:FAIL in (redundant-let-test) (main_test.clj:34)
324:FAIL in (read-error-test) (main_test.clj:238)
331:FAIL in (exclude-clojure-test) (main_test.clj:210)
337:FAIL in (inline-def-test) (main_test.clj:19)
522:FAIL in (invalid-arity-test) (main_test.clj:117)
12:ERROR in (run!-test) (Pattern.java:2027)
115:ERROR in (cache-test) (ProcessBuilder.java:1128)
343:ERROR in (import-vars-test) (ProcessBuilder.java:1128)
#2019-11-2419:31littleli@sogaiu that is 6 failures, isn't it?#2019-11-2419:31sogaiui think so#2019-11-2419:31sogaiuand yet, i see what i see in my output 🙂#2019-11-2419:33sogaiuoh wait#2019-11-2419:33sogaiui see a few cljs things i missed#2019-11-2419:33borkdudeIt might now be better to run the script/test.bat file#2019-11-2419:33borkdudeit will download some necessary deps#2019-11-2419:34borkdudethat will be used to extract info from#2019-11-2419:35sogaiu@ales.najmann i missed some -- now i think my list is complete#2019-11-2419:35borkdude(pushed a fix for the bat)#2019-11-2419:38sogaiui have 3 extract-cljs-core-vars-test which littleli didn't get it seems#2019-11-2419:39borkdudelet's hope appveyor will work now#2019-11-2419:39borkdudehttps://ci.appveyor.com/project/borkdude/clj-kondo/builds/29085181#2019-11-2419:40sogaiui hope we don't have to use windows 7.1 sdk at some point#2019-11-2419:42sogaiunot having much luck with test.bat#2019-11-2419:42sogaiu
'clojure' is not recognized as an internal or external command,
operable program or batch file.
'clojure' is not recognized as an internal or external command,
operable program or batch file.
'clojure' is not recognized as an internal or external command,
operable program or batch file.
'else' is not recognized as an internal or external command,
operable program or batch file.
"Testing with Clojure 1.9.0"
'clojure' is not recognized as an internal or external command,
operable program or batch file.
Terminate batch job (Y/N)? y
#2019-11-2419:42sogaiuright after that invoking clojure manually works#2019-11-2419:43borkdudelol:
#2019-11-2419:43borkdude
Adding ~\scoop\shims to your path.
'lastupdate' has been set to '2019-11-24T19:42:43.8238427+00:00'
Scoop was installed successfully!
Type 'scoop help' for instructions.
powershell -Command "scoop install clojure"
scoop : The term 'scoop' is not recognized as the name of a cmdlet, function, 
script file, or operable program. Check the spelling of the name, or if a path 
was included, verify that the path is correct and try again.
At line:1 char:1
+ scoop install clojure
+ ~~~~~
    + CategoryInfo          : ObjectNotFound: (scoop:String) [], CommandNotFou 
   ndException
    + FullyQualifiedErrorId : CommandNotFoundException
 
Command exited with code 1
#2019-11-2419:44littleliadding bucket is missing? 🙂#2019-11-2419:44borkdude> scoop : The term 'scoop' is not recognized#2019-11-2419:44littlelidamn!#2019-11-2419:44borkdudeI'll try this as the first step so I don't have to wait for the compilation to finish#2019-11-2419:45borkdude
Adding ~\scoop\shims to your path.
'lastupdate' has been set to '2019-11-24T19:45:23.8762273+00:00'
Scoop was installed successfully!
Type 'scoop help' for instructions.
scoop install clojure"
'scoop' is not recognized as an internal or external command,
operable program or batch file.
Command exited with code 1
#2019-11-2419:45borkdudeMaybe it needs a fresh shell#2019-11-2419:46sogaiufun with quoting issues:
> clojure -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.9.0"}}}' -Spath
Error while parsing option "--config-data {:deps {org.clojure/clojure {:mvn/version 1.9.0}}}": java.lang.NumberFormatException: Invalid number: 1.9.0
#2019-11-2419:47borkdudefresh shell didn't work#2019-11-2419:48sogaiutwo sets of double quotes seems to work as per the tools.deps wiki advice, fwiw#2019-11-2419:48sogaiu
> clojure -Sdeps '{:deps {org.clojure/clojure {:mvn/version ""1.9.0""}}}' -Spath
src;parser;resources;inlined;C:\Users\user\.m2\repository\com\cognitect\transit-java\0.8.337\transit-java-0.8.337.jar;C:\Users\user\.m2\repository\org\clojure\clojure\1.9.0\clojure-1.9.0.jar;C:\Users\user\.m2\repository\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;C:\Users\user\.m2\repository\io\lambdaforge\datalog-parser\0.1.1\datalog-parser-0.1.1.jar;C:\Users\user\.m2\repository\org\clojure\core.specs.alpha\0.1.24\core.specs.alpha-0.1.24.jar;C:\Users\user\.m2\repository\org\clojure\spec.alpha\0.1.143\spec.alpha-0.1.143.jar;C:\Users\user\.m2\repository\com\fasterxml\jackson\dataformat\jackson-dataformat-cbor\2.9.6\jackson-dataformat-cbor-2.9.6.jar;C:\Users\user\.m2\repository\com\googlecode\json-simple\json-simple\1.1.1\json-simple-1.1.1.jar;C:\Users\user\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.9.6\jackson-core-2.9.6.jar;C:\Users\user\.m2\repository\org\javassist\javassist\3.18.1-GA\javassist-3.18.1-GA.jar;C:\Users\user\.m2\repository\org\msgpack\msgpack\0.6.12\msgpack-0.6.12.jar;C:\Users\user\.m2\repository\com\cognitect\transit-clj\0.8.313\transit-clj-0.8.313.jar;C:\Users\user\.m2\repository\cheshire\cheshire\5.8.1\cheshire-5.8.1.jar;C:\Users\user\.m2\repository\tigris\tigris\0.1.1\tigris-0.1.1.jar;C:\Users\user\.m2\repository\com\fasterxml\jackson\dataformat\jackson-dataformat-smile\2.9.6\jackson-dataformat-smile-2.9.6.jar;C:\Users\user\.m2\repository\javax\xml\bind\jaxb-api\2.3.0\jaxb-api-2.3.0.jar
#2019-11-2419:49borkdudePR welcome#2019-11-2419:49sogaiulol#2019-11-2419:50sogaiubeing pulled away by niece, sorry 🙂#2019-11-2419:51borkdudehehe, np#2019-11-2419:55borkdudeah now scoop works#2019-11-2419:57borkdudeadded the double quotes#2019-11-2419:58borkdude
Installing PowerShell module 'ClojureTools'
Linking ~\scoop\modules\ClojureTools => ~\scoop\apps\clojure\current
'clojure' (1.10.1.489) was installed successfully!
'clojure' suggests installing 'java/adopt8-hotspot' or 'java/adoptopenjdk-lts-hotspot' or 'java/oraclejdk' or 'java/openjdk'.
clojure
'clojure' is not recognized as an internal or external command
#2019-11-2419:58littlelialmost, I see the same issue as on my machine#2019-11-2419:59littleliI cannot for example run script/test.bat for the same error#2019-11-2420:01borkduderunning clojure from powershell does seem to work, but not from the cmd.exe, using your scoop @ales.najmann?#2019-11-2420:01borkdudeusing powershell I now get:
clojure
The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: Downloading: org/clojure/clojure/1.10.1/clojure-1.10.1.pom from 
#2019-11-2420:02borkdude(on Appveyor)#2019-11-2420:02littleliI bet that for that reasons there were those shims in the some of the previous versions#2019-11-2420:03littleli"bin" section, see https://github.com/littleli/scoop-clojure/blob/542f156735757aaf007e63aee3a13eba5be422e3/clojure.json#L9#2019-11-2420:05borkdudeso what's the next action that should be taken?#2019-11-2420:06borkdudeshould I add those "-NoProfile -ExecutionPolicy Bypass -Command Invoke-Clojure" to the powershell command?#2019-11-2420:07littleliI think more important is it actually runs powershell.exe as a shell#2019-11-2420:07borkdudeyes:
- ps: clojure
#2019-11-2420:10borkdude@ales.najmann :
init:
- ps: iex (new-object net.webclient).downloadstring('')
- ps: scoop bucket add java
- ps: scoop bucket add scoop-clojure 
- ps: scoop install java/adopt8-hotspot
- ps: scoop install clojure
- ps: clojure
it fails in the last step
#2019-11-2420:10borkdudeI can try Set-ExecutionPolicy RemoteSigned -scope CurrentUser#2019-11-2420:11borkdudehm: Set-ExecutionPolicy : The method or operation is not implemented. At line:1 char:1 + Set-ExecutionPolicy RemoteSigned -scope CurrentUser#2019-11-2420:13littlelican you execute: scoop which clojure ?#2019-11-2420:13littleliit is a scoop alternative to unix which#2019-11-2420:15borkdudeno output:
Linking ~\scoop\modules\ClojureTools => ~\scoop\apps\clojure\current
'clojure' (1.10.1.489) was installed successfully!
scoop which clojure
git clone -q --branch=windows-tests  C:\projects\clj-kondo
git checkout -qf 957d1efacc3b9f4dfc8015de2ec6b828dd25e4b5
cmd /C "set CLJ_KONDO_TEST_ENV=jvm && call script/test.bat"
'clojure' is not recognized as an internal or external command,
operable program or batch file.
'clojure' is not recognized as an internal or external command,
operable program or batch file.
#2019-11-2420:21borkdudeI'll deprecate clojure in the script until we find this out#2019-11-2420:21littleliafaik, it is correct, because clojure really is a powershell alias, actually defined directly in distribution from official source. There is psmodule definition. You can find it here on this path: \scoop\apps\clojure\current#2019-11-2420:21littleliwell, i think what could help is to add some shim that does not interfere with tools like calva#2019-11-2420:22littleliI don't know... clj-cmd, it will be eventually able to run as a command. because scoop creates shim binary for the command, and you can use clj-cmd.exe as a launching command. but that is theoretical.#2019-11-2420:23borkdudecalva? this is on CI#2019-11-2420:23littlelior you could try to use powershell instead of cmd.exe#2019-11-2420:23littleliyes, but I removed shim creation because there was weird issue with calva#2019-11-2420:24littlelihttps://github.com/littleli/scoop-clojure/issues/5#2019-11-2420:24borkdudescoop which was already ran using powershell, not cmd.exe#2019-11-2420:25littleliagain, clojure is not a command, it is powershell alias... so cmd.exe sees nothing, right? 🙂#2019-11-2420:26littleli
PS C:\Users\alesn> cmd                                                                                                                                                                                                           Microsoft Windows [Version 10.0.18362.476]
(c) 2019 Microsoft Corporation. Všechna práva vyhrazena.

C:\Users\alesn>clojure
'clojure' is not recognized as an internal or external command,
operable program or batch file.
#2019-11-2420:26borkdudeyes, I wasn't using cmd.exe#2019-11-2420:26borkdude
- ps: scoop which clojure
#2019-11-2420:26borkdudeps means powershell#2019-11-2420:27borkdudethe lein tests appear to be running now though: https://ci.appveyor.com/project/borkdude/clj-kondo#2019-11-2420:27littleli
PS C:\Users\alesn> scoop which clojure                                                                                                                                                                                           Not a scoop shim.
#2019-11-2420:28littleliwhich is correct, there should be no shims. unfortunately this is not visible in the above output 😕#2019-11-2420:28borkdudemaybe a hardcoded c:\projects\foo\clojure works,#2019-11-2420:29littleliit's quite confusing, right? 🙂#2019-11-2420:34borkdudeonly 10 failures and 2 errors on appveyor, progress. clojure is needed to download a few deps#2019-11-2420:35borkdudeI'm done for today, PRs still welcome to the windows-tests branch 🙂#2019-11-2420:44littlelibtw lein is in scoop too, in the main bucket.#2019-11-2421:07sogaiuin test.bat, was putting powershell -command in front of the clojure invocations somehow problematic? i see test output here via powershell as well as cmd.#2019-11-2421:11borkdudeno, but scoop which clojure did not work, neither did ps: clojure#2019-11-2421:11borkdudeI now eliminated the need for clojure in the .bat script#2019-11-2421:12sogaiuah, less is more#2019-11-2421:18littleliProbably the alias is not activated right after installation but is required to be activated similarly to how update to profile shell files is required to be run on unices (with source command)#2019-11-2508:25borkdudeAll JVM tests are succeeding now on Windows 😄 Ran 121 tests containing 1207 assertions. 0 failures, 0 errors.#2019-11-2514:54sogaiunice! thanks to @ales.najmann for help 🙂#2019-11-2515:14borkdudeYes, thank you both!#2019-11-2509:24borkdudeThere is one remaining native test error:
lein test clj-kondo.main-test
Unexpected error. Please report an issue.
lein test :only clj-kondo.main-test/deprecated-var-test
FAIL in (deprecated-var-test) (main_test.clj:1945)
config
expected: (clojure.core/= (clojure.core/count maps__8060__auto__) (clojure.core/count res__8061__auto__))
  actual: (not (clojure.core/= 1 0))
Unexpected error. Please report an issue.
Unexpected error. Please report an issue.
Unexpected error. Please report an issue.
Unexpected error. Please report an issue.
#2019-11-2509:24borkdudeThis only seems to occur when you run all native tests, not when I run this test in isolation#2019-11-2509:24borkdudeMight we worth investigating.#2019-11-2509:25borkdudeSee output here: https://ci.appveyor.com/project/borkdude/clj-kondo/builds/29095038#2019-11-2509:26borkdudeOh, it looks like I ran the wrong test (typo) in isolation.#2019-11-2509:33borkdude
FAIL in (deprecated-var-test) (main_test.clj:1945)
config
expected: (clojure.core/= (clojure.core/count maps__761__auto__) (clojure.core/count res__762__auto__))
  actual: (not (clojure.core/= 1 0))
Ran 1 tests containing 15 assertions.
1 failures, 0 errors.
Tests failed.
This is only when testing the native version.
#2019-11-2519:31sogaiuI commented out what looked like what was leading to that:
#_(testing "config"
    (assert-submaps
     '({:file "corpus/deprecated_var.clj",
        :row 10,
        :col 1,
        :level :warning,
        :message "#'foo.foo/deprecated-fn is deprecated"})
in my output, there are the following lines right after the FAIL, whether the section is commented or not:
Unexpected error. Please report an issue.
Unexpected error. Please report an issue.
Unexpected error. Please report an issue.
Unexpected error. Please report an issue.
#2019-11-2519:31sogaiudid you see this?#2019-11-2519:35borkdudeah then those might be caused by something else... hm#2019-11-2519:35borkdudein main.clj this line is printed. maybe you can include (.getMessage e) in the println#2019-11-2519:37sogaiui can try that -- though in my main.clj there is something about printing the stacktrace. is there some reason i'm not seeing any info about the stacktrace?#2019-11-2519:41borkdudeyes, because that text is going to *err*#2019-11-2519:41borkdudeand normal println is going to stdout#2019-11-2519:41borkdudewhich is not consistent in this case, but stderr is not visible I think in the tests (which could be a nice for debugging)#2019-11-2519:42sogaiuthanks for the explanation -- build with patch complete, waiting for test output 🙂#2019-11-2519:45sogaiu
lein test clj-kondo.main-test
Unexpected error. Please report an issue. clojure.lang.Symbol cannot be cast to java.lang.String
Unexpected error. Please report an issue. clojure.lang.Symbol cannot be cast to java.lang.String
Unexpected error. Please report an issue. Unsupported character: \\.specs$
Unexpected error. Please report an issue. Unsupported character: \\.specs$
#2019-11-2519:51borkdudeaha... interesting. maybe you can print the entire stacktrace to stdout? which is an argument to .printStackTrace#2019-11-2519:52sogaiusounds good, just need to figure out the details of how -- will bug you if i have trouble 🙂#2019-11-2520:13borkdudeProbably just (.printStackTrace e System/out)#2019-11-2520:14sogaiui did something different -- but may be that would have been enough. too much output so adding to issue.#2019-11-2520:14sogaiugithub seems to not like my comment 😞#2019-11-2520:14sogaiuhttps://pastebin.com/KwdEZHSS#2019-11-2520:14sogaiui guess they are still having issues#2019-11-2520:15borkdudeI forgot to compile with clojure 1.10.1 which I do in linux.#2019-11-2520:15borkdudemaybe it has to do with that, but clj-kondo also should be able to run with clojure 1.9.0, so I don't know#2019-11-2520:17sogaiui'm puzzled as to why the test framework doesn't explain better which test(s) it's experiencing these issues with.#2019-11-2520:18borkdudemaybe it has to do with how I process the result from the shell output#2019-11-2520:19sogaiumay be so -- but i feel like blaming the test framework 🙂#2019-11-2520:19borkdudehaha#2019-11-2520:21sogaiuok, i guess i'll change compile.bat to include: call lein with-profiles +clojure-1.10.1 do clean, uberjar then?#2019-11-2520:22borkdudeI already pushed it now#2019-11-2520:22sogaiugreat#2019-11-2520:25sogaiui allocated another core to my vm to cope with slowness..it's gradually eating away at my real computing resources 🙂#2019-11-2520:28sogaiucurious...`lein test` leads to this: https://pastebin.com/7a9GwMqj#2019-11-2521:03borkdudeI found this out:
Could not parse config! Unsupported character: \\.* "{:linters {:unused-binding {:level :off}, :unresolved-symbol {:level :off}, :refer-all {:level :off}, :type-mismatch {:level :off}, :deprecated-var {:exclude #:foo.foo{deprecated-fn {:namespaces [foo.bar bar\\\\.*], :defs [foo.baz/allowed foo\\\\.baz/ign\\\\.*]}}}}}"
#2019-11-2521:04borkdude> Caused by: java.lang.ClassNotFoundException: clojure.core$with_meta__5420 That's usually caused by stale target files#2019-11-2521:04borkdudelein clean solves it#2019-11-2521:04borkdude(already added it)#2019-11-2521:08borkdudesomehow the backslashes get doubled#2019-11-2521:09borkdudehttps://stackoverflow.com/questions/34402429/processbuilder-does-something-to-my-command-line-arguments-on-windows#2019-11-2521:10sogaiuwherever we turn, there is the windows escaping beast...there is no escape...or should i say, there is always escape?#2019-11-2521:13sogaiui don't understand, lein clean was in the original compile.bat file -- i pulled and tried building + test, and i still see an exception. am i misunderstanding?#2019-11-2521:14borkdudethe most recent commit is 3efab387e2842c0f5b138bdf30ededccb6b68abd#2019-11-2521:15borkdudeit should work with that one. see appveyor (the error was there as well, but is now fixed)#2019-11-2521:15sogaiuah, running lein clean after building but before lein test? that seems to be working.#2019-11-2521:15borkdudeyes#2019-11-2521:16sogaiuok, now i get it, thanks#2019-11-2521:16sogaiui think i'm still seeing the same exceptions during the test#2019-11-2521:16sogaiui am on 3efab387#2019-11-2521:17sogaiuthis is the quote thing then?#2019-11-2521:35borkdudewhat exceptions do you see?#2019-11-2521:37sogaiui think it's the same as before, but here is a fresh copy-paste: https://pastebin.com/m0ntm5fB#2019-11-2521:39sogaiusorry, for completeness: https://pastebin.com/stgtSMJk#2019-11-2521:39borkdudeit's the same issue:
"{:linters {:unused-binding {:level :off}, :unresolved-symbol {:level :off}, :refer-all {:level :off}, :type-mismatch {:level :off}, :unused-namespace {:exclude [.*\\\\.specs$]}}}"
cannot be parsed as EDN, somehow the backslashes get doubled by ProcessBuilder
#2019-11-2521:39borkdudeon Windows#2019-11-2521:42sogaiuok, thanks#2019-11-2521:44borkdudeat least that's what I think#2019-11-2521:45borkdudelint-native! that is where the EDN config gets passed as a string#2019-11-2521:45borkdudeto the conch library and this uses the ProcessBuilder to make the program call#2019-11-2521:47borkdudebut hey, this worked in the normal JVM tests#2019-11-2521:47borkdudeso that's kinda weird isn't it#2019-11-2521:47sogaiuit is weird#2019-11-2521:47borkdudeoh well, no, then the string isn't handled via the processbuilder#2019-11-2521:48sogaiuthis has nothing to do with regexp, right?#2019-11-2521:48borkdudeno#2019-11-2521:48sogaiuok, because there seems to be something wonky about native-image and asterisk#2019-11-2521:48sogaiuthat's a different thing#2019-11-2521:49borkdudeoh is that it maybe?#2019-11-2521:50sogaiuno idea -- but we used {0,} as a substitute for * to get native-image to succeed in working with building at some point recently, right?#2019-11-2521:51sogaiui think that's a separate thing#2019-11-2521:51borkdudeif you put this into an EDN file:
{:linters {:unused-binding {:level :off}, :unresolved-symbol {:level :off}, :refer-all {:level :off}, :type-mismatch {:level :off}, :unused-namespace {:exclude [.*\\\\.specs$]}}}
you will get: user=> (edn/read-string (slurp "/tmp/foo.edn")) Execution error at user/eval3 (REPL:1). Unsupported character: \\.specs$
#2019-11-2521:51borkdudeand it seems the slashes are doubled somehow#2019-11-2521:52borkdudehuh#2019-11-2521:52borkdudewait, the dollar sign is also weird#2019-11-2521:52borkdudeah, it has to do with quotes probably#2019-11-2521:52borkdudethe quotes are missing#2019-11-2521:53sogaiui don't seem them, yes#2019-11-2521:53sogaiuisn't the whole thing (from left curly to right curly) in quotes?#2019-11-2521:54borkdudelet me just print the config before it goes through#2019-11-2522:01borkdudeok, so this works:
(edn/read-string "{:linters {:unused-binding {:level :off}, :unresolved-symbol {:level :off}, :refer-all {:level :off}, :type-mismatch {:level :off}, :deprecated-var {:exclude #:foo.foo{deprecated-fn {:namespaces [foo.bar \"bar\\\\.*\"], :defs [foo.baz/allowed \"foo\\\\.baz/ign\\\\.*\"]}}}}}")
#2019-11-2522:02borkdudebut somehow the quotes disappear#2019-11-2522:03borkdudehttps://bugs.java.com/bugdatabase/view_bug.do?bug_id=6511002#2019-11-2522:05borkdudenot sure if that's related but maybe the quotes have to be doubled for Windows?#2019-11-2522:05borkdudeah this looks like it: https://bugs.openjdk.java.net/browse/JDK-8131908#2019-11-2522:06sogaiucould be - am reading - fwiw, there is a quoting tips section in the clj-on-windows tools.deps wiki page#2019-11-2522:06borkdudeSun/Oracle refers to this document: https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments?redirectedfrom=MSDN&amp;view=vs-2019
#2019-11-2522:08sogaiulooking#2019-11-2522:10sogaiui roll my eyes at the response at the bottom of JDK-8131908#2019-11-2522:10sogaiuhow is anyone supposed to know what is sitting inside processbuilder on windows?#2019-11-2522:11sogaiuthere is no mention of "windows" nor "quote" at: https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#2019-11-2522:11sogaiunor "escape"#2019-11-2522:12sogaiusorry, getting carried away 🙂#2019-11-2522:14sogaiudidn't lread summarize some quoting issues related to windows in some jira issue?#2019-11-2522:15sogaiuso this whole thing is because a string is being passed on the command line, right?#2019-11-2522:17borkdudeyes, I now tried something#2019-11-2522:17borkdudebut I didn't test it on Windows yet, so pushed it to appveyor#2019-11-2522:18borkdudeit worked 🙂#2019-11-2522:18sogaiuhurray!#2019-11-2522:18borkdudeall tests passing now!#2019-11-2522:19borkdudewill do come clean up tomorrow and then merge#2019-11-2522:19sogaiuawesome! > If an odd number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is "escaped" by the remaining backslash, causing a literal double quotation mark (") to be placed in argv. i guess you did this?#2019-11-2522:20borkdudeI did this:
config (if windows? (str/replace config "\"" "\\\"")
                    config)

```
#2019-11-2522:20borkdude(damn slack with their new markup thing)#2019-11-2522:20sogaiui was hoping there was a way to revert -- i guess not#2019-11-2522:20sogaiutime for rest perhaps 🙂#2019-11-2522:21sogaiuoh, only a few more entries on this thread#2019-11-2522:21sogaiuand i can reach 100#2019-11-2522:21sogaiu😉#2019-11-2522:23borkdudehow many now?#2019-11-2522:23borkdudeah nice, we broke a record!#2019-11-2522:24sogaiulol, i can only easily tell that it's over 100#2019-11-2514:22eraserhdIt turns out that my editors lint support saves the buffer to a temporary directory before linting, so the feature of finding config from the path doesn't actually help me. :/#2019-11-2514:46borkdudeoh shit. would it be better to revert your commit?#2019-11-2514:47borkdudeI guess it still works as before since it fallbacks on the cwd behavior right?#2019-11-2514:48borkdudesome plugins allow the current working directory to be configured based on the file that is being linted#2019-11-2514:48borkdudelike IntelliJ#2019-11-2514:50eraserhdWell, I don't have evidence, but I suspect the feature is still useful generally. And yeah, it doesn't hurt anythin.g#2019-11-2514:51eraserhdI'm asking a question in the editor's IRC about how we want to proceed. Perhaps we'll change how the linter works.#2019-11-2515:00delaguardohttps://github.com/marketplace/actions/setup-clj-kondo setup-clj-kondo for hosted runners in github actions is here) including latest clj-kondo.exe for running on windows#2019-11-2515:04borkdudenice !#2019-11-2515:05borkdude@eraserhd if I'm not mistaking flycheck has the same behavior actually. because you don't have to save the file for linting, it makes a copy of it somewhere and then lints that file#2019-11-2515:05borkdudeusing the cwd of the file (I think the dir the file lives in)#2019-11-2515:06borkdudeso it might actually slow things down a bit, but probably not noticable#2019-11-2515:07eraserhdOk, I'll look into that. If this is something that several linters need, I'll fix the editor.#2019-11-2515:07borkdudemaybe the linting behavior of kakaune should be the same, setting the cwd to the parent dir of the file#2019-11-2515:08borkdudeI forgot how much nicer Parallels is than VirtualBox#2019-11-2515:08borkdudeand so far no crashes#2019-11-2515:09borkdude@eraserhd but this behavior could still be useful for VSCode, I'll have to manually test it. Please keep me updated if we should keep this behavior and if nobody is using it (and it's not useful for VSCode) we can maybe deprecate it again#2019-11-2515:10borkdudehttps://github.com/borkdude/clj-kondo/issues/630#2019-11-2522:25borkdude@eraserhd fwiw, I think emacs does the following: it saves the intermediate state of a file to a tmp file and then invokes the linter piping the input from the tmp file to stdin#2019-11-2522:25borkdudeso clj-kondo only sees the path "stdin", not even the filename#2019-11-2522:26borkdudeso in that case the new feature isn't very beneficial. however I think in the case of VSCode marco morains plugin, it's invoked on save and then using the filename, so it works for that case#2019-11-2522:28borkdudeAll JVM + native tests are passing for Windows now: https://ci.appveyor.com/project/borkdude/clj-kondo/builds/29113922#2019-11-2522:29borkdude(thanks again @ales.najmann and @sogaiu for mentally supporting me and providing useful additions)#2019-11-2612:47borkdudeI've tried out a branch with pmap instead of map. Old:
$ /usr/local/bin/clj-kondo --lint $(clj -Spath)
linting took 1436ms, errors: 133, warnings: 363
New:
linting took 895ms, errors: 135, warnings: 363
It's almost cheating 🙂
#2019-11-2612:49kszabowhy did the errors/warnings change? 🙂#2019-11-2612:49borkdudegood point! I'll upgrade clj-kondo first...#2019-11-2612:50kszabofor even better returns, try using upmap from https://github.com/TheClimateCorporation/claypoole#2019-11-2612:50borkdudeupdated#2019-11-2612:50kszaboas order doesn’t matter AFAIK#2019-11-2612:50borkdudethere's still 2 errors, let me check what they are#2019-11-2612:54borkdudehmm, I think there is a bug, still nice idea. 😛#2019-11-2612:55borkdudeupmap is nice, but I don't think clj-kondo can profit from it, as everything's analyzed, then the results are ordered, etc.#2019-11-2614:47borkdudeWindows tests merged to master#2019-11-2617:10sogaiutried the tests from master on windows and they seemed to run without problems :thumbsup:#2019-11-2617:22borkdude😄#2019-11-2618:23borkdudeAny feedback on this issue? https://github.com/borkdude/clj-kondo/issues/633#2019-11-2619:23sogaiu@borkdude probably not what you're looking for, but if there were a canonical way (so not specific to clj-kondo) to store annotative info outside of source, that could be a nice place for such info. i've been looking for something like this for a while so if someone knows of such a way, would be happy to hear more about it.#2019-11-2719:10tschadyis there a way to use the analysis output to ignore certain instances of error/warning? My use case is to have a file of grandfathered errors that I chip away at over time, while disallowing new errors.#2019-11-2719:22borkdude@tws is this for CI usage?#2019-11-2719:23tschadygoing forward, CI. over time, cleanup a legacy codebase.#2019-11-2719:25tschadye.g. I want docstrings required on all new fns, but too many old ones to handle#2019-11-2719:28tschadyseems like saving the analysis output, editing it down to those i want to ignore, and leaving in .clj-kondo/ might work#2019-11-2719:33borkdude@tws 1. save the current findings (EDN output :findings key) somewhere as a baseline 2. save the future findings to a file 3. find only the new findings using a small Clojure script (babashka may come in handy if you want it to be fast). 4. print those findings in CI or do whatever you want to do with it#2019-11-2719:33borkdudesomething like that#2019-11-2719:33tschadyseems reasonable. i was hoping there was some builtin i couldn’t find to #3#2019-11-2719:34borkdudefor the printing you could maybe use clj-kondo.core/print!#2019-11-2719:35borkdudeNote that clj-kondo also works as a JVM lib, so you can also do it from a small Clojure jvm program#2019-11-2719:44tschady@borkdude love “needs hammock time” swimlane btw. I’m going to steal that.#2019-11-2719:45tschadywould you consider this as a feature? happy to make an issue. Basically above. A file inside .clj-kondo/ , probably in analytics format, where duplicate errors/warnings are supressed?#2019-11-2719:48borkdudeI think for now it falls more in the category of things you can do with scripting yourself, given the output of clj-kondo. See for examples: https://github.com/borkdude/clj-kondo/tree/master/analysis If enough people are asking for this, I will consider it.#2019-11-2719:49borkdudeYou can make an issue for it anyway, please be as detailed as possible about your use case.#2019-11-2719:49borkdudeAnd also include the information from this slack conversation#2019-11-2720:10tschadysure. I was asking “no”, or “maybe yes”. Seems like maybe. thanks.#2019-11-2721:18dominicmYou should look at revoewdog#2019-11-2721:18dominicmIt does this for you#2019-11-2721:37borkdude^ @tws (reviewdog)#2019-11-2812:37borkdudewant to help test a new feature? warnings about missing requires: linux https://7518-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.11.24-SNAPSHOT-linux-amd64.zip mac: https://7517-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.11.24-SNAPSHOT-macos-amd64.zip branch: missing-require example:#2019-11-2813:49ericdalloThank you for this very useful feature. I tested on my Debian 10 linux using the binary above and it seems to work nice#2019-11-2812:38borkdudeThe name of the linter and the message are subject to change, feel free to post suggestions at https://github.com/borkdude/clj-kondo/issues/339#2019-11-2813:52stathissiderishello, is there a way to exclude certain namespaces (with a regex) from being checked for :unresolved-symbol?#2019-11-2813:55borkdudehttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md I don't think so (yet). Do you have an example of how this would be useful?#2019-11-2813:59stathissideris@borkdude I use hugsql in namespaces that all end in .data and I’d rather not declare all my hugsql-generated functions#2019-11-2814:00borkdudeso the vars are foo.data/bar?#2019-11-2814:01stathissideriscorrect#2019-11-2814:01borkdudeI guess the regex could be "\\.data/.*" in that linter. PR welcome I think#2019-11-2814:02stathissiderisok, thanks!#2019-11-2814:02stathissiderisby the way, does this look ok to you? :unresolved-symbol {:exclude [(secretary.core [defroute])]}#2019-11-2814:02borkdudecould you first make an issue about it with a proposed solution and then a corresponding PR?#2019-11-2814:03borkdudeI think that looks ok#2019-11-2814:03borkdudeisn't it working?#2019-11-2814:03stathissiderisit seems to crash clj-kondo
Unexpected error. Please report an issue.
java.lang.IllegalArgumentException: no conversion to symbol
	at clojure.core$symbol.invokeStatic(core.clj:596)
	at clojure.core$symbol.invoke(core.clj:589)
	at clj_kondo.impl.config$fn__4141$delayed_cfg__4142$fn__4144.invoke(config.clj:187)
	at clojure.lang.ArrayChunk.reduce(ArrayChunk.java:63)
	at clojure.core.protocols$fn__8139.invokeStatic(protocols.clj:136)
	at clojure.core.protocols$fn__8139.invoke(protocols.clj:124)
	at clojure.core.protocols$fn__8099$G__8094__8108.invoke(protocols.clj:19)
	at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:31)
	at clojure.core.protocols$fn__8131.invokeStatic(protocols.clj:75)
	at clojure.core.protocols$fn__8131.invoke(protocols.clj:75)
	at clojure.core.protocols$fn__8073$G__8068__8086.invoke(protocols.clj:13)
	at clojure.core$reduce.invokeStatic(core.clj:6828)
	at clojure.core$reduce.invoke(core.clj:6810)
	at clj_kondo.impl.config$fn__4141$delayed_cfg__4142.invoke(config.clj:186)
	at clojure.lang.AFn.applyToHelper(AFn.java:154)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.core$apply.invokeStatic(core.clj:665)
	at clojure.core$memoize$fn__6862.doInvoke(core.clj:6353)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clj_kondo.impl.config$fn__4141$fn__4150.invoke(config.clj:195)
	at clj_kondo.impl.namespace$reg_unresolved_symbol_BANG_.invokeStatic(namespace.clj:162)
	at clj_kondo.impl.namespace$reg_unresolved_symbol_BANG_.invoke(namespace.clj:157)
	at clj_kondo.impl.linters$lint_var_usage$iter__5082__5090$fn__5091$iter__5084__5092$fn__5093.invoke(linters.clj:239)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:51)
	at clojure.lang.RT.seq(RT.java:531)
	at clojure.core$seq__5387.invokeStatic(core.clj:137)
	at clojure.core$seq__5387.invoke(core.clj:137)
	at clj_kondo.impl.linters$lint_var_usage$iter__5082__5090$fn__5091.invoke(linters.clj:201)
#2019-11-2814:07borkdude@stathissideris ah gotcha:
$ clj -A:clj-kondo --config '{:linters {:unresolved-symbol {:exclude [(secretary.core/defroute)]}}}' --lint - <<< "(require '[secretary.core]) (secretary.core/defroute foo)"
linting took 61ms, errors: 0, warnings: 0
#2019-11-2814:07borkdudethe vector is for excluding specific symbols within a call#2019-11-2814:07borkdudeI'm thinking about deprecating this syntax maybe, since it's a bit odd maybe#2019-11-2814:07stathissiderisoooh, sorry, I misread the manual#2019-11-2814:08borkdudeno problem. there is an issue for a config validator. once that's there, we should no longer have to bother with this kind of problem#2019-11-2814:09stathissiderisso any pointers on where I could start with implementing the new exclusion for the :unresolved-symbol linter?#2019-11-2814:11borkdude@stathissideris yes: here is the related config code: https://github.com/borkdude/clj-kondo/blob/de8add6672d5c795a0012e6ba9043f3bfe4b9c4b/src/clj_kondo/impl/config.clj#L179 and here is a config that already uses regexes, as an example: https://github.com/borkdude/clj-kondo/blob/de8add6672d5c795a0012e6ba9043f3bfe4b9c4b/src/clj_kondo/impl/config.clj#L161#2019-11-2814:11stathissideristhanks, I’ll have a look!#2019-11-2814:12borkdudeif you have a suggestion for a map-based configuration format instead of the vector with lists or symbols, feel free to come up with one as well#2019-11-2814:12borkdudebecause one problem now is that this config isn't merged with built-in ones (e.g. clojure.test/is)#2019-11-2814:12stathissiderisone thing that was a bit unexpected in the config is that each linter seems to expect different (but kinda similar) configs#2019-11-2814:13borkdudeThe related issue for that one is: https://github.com/borkdude/clj-kondo/issues/608#2019-11-2814:13borkdudeMaybe two separate PRs would be nice. Optional of course.#2019-11-2814:14borkdudeI think it's good to discuss some alternative formats first before implementing it. But this is another feature really, so let's just focus on the regex first 🙂#2019-11-2814:16borkdudeIt might be slightly related though, since the regex feature may affect the "ignore in call" exclusion or the symbol itself#2019-11-2814:22stathissideris@borkdude thank you so much by the way, I’m finding bugs with clj-kondo#2019-11-2817:27yuhanI had a semi-working branch for that exact feature, could try and polish it up and submit a PR over the weekend!#2019-11-2817:28yuhanMy use case was wanting to support Meander macros and ignore all unresolved-symbol warnings for symbols ending with ! and ?#2019-11-2817:28yuhanone odd quirk I found with the regex configurations was how they don't accept actual #"" regex literals and require string literals with double-escaped backslashes#2019-11-2819:20borkdude@qythium that is because EDN doesn't support regexes#2019-11-2819:21borkdudebut I do actually support it with edamame (which is a configurable EDN parser), but clj-kondo predates it#2019-11-2820:59eraserhdSince US is on holiday, I finally have space to think about this clj-kondo current directory thing.#2019-11-2821:01eraserhdI think I'm concluding that ideally, I want to lint stdin, but supply the filename somehow so that the clj-kondo can find the config directory.#2019-11-2821:02eraserhdeslint (the first one I checked) does this with --stdin and --stdin-filename options.#2019-11-2821:22borkdude@eraserhd - is already there for linting stdin, --stdin-filename would that only be used for finding the config dir? then we could also have --cwd which overrides the current working directory?#2019-11-2821:25eraserhd--stdin-filename would also provide a default for --lang.#2019-11-2821:26borkdudetrue#2019-11-2821:26borkdudealright, seems good then#2019-11-2821:26eraserhdOh, to disclose: I'm still pondering. This proposal seems the most "correct", although it requires a bit of rework on the editor part.#2019-11-2821:26eraserhdSome other linters don't support linting stdin. cppcheck being one of them.#2019-11-2821:27borkdude@marc-omorain’s plugin also doesn't use stdin, it uses the raw file + filename, so there it still make sense what we're currently doing#2019-11-2821:28borkdudeflycheck (emacs) sets the cwd to the dir of the file being linted#2019-11-2821:29eraserhdhuh. That's actually an easy fix. That suggests all linters can find their config in a parent directory?#2019-11-2821:29borkdudeyes#2019-11-2821:30borkdudeehm, I don't know for all linters#2019-11-2821:30borkdudebut I'm happy it works that way#2019-11-2821:30eraserhdBut anything that works with flycheck, which is most.#2019-11-2821:30borkdudebecause I anticipated the same problem for a multi-project git repo, then I checked, and I was happy that it worked in my case (having two .clj-kondo dirs in the same repo)#2019-11-2821:31borkdude@eraserhd aren't you talking from the perspective of kakoune?#2019-11-2821:31eraserhdWell, I'm trying to have a wider perspective and do the "most natural" thing.#2019-11-2821:32borkdudeadopting the flycheck behavior requires no changes to clj-kondo#2019-11-2821:33eraserhdHmm, well changing to the linted file's directory is easy, but it still writes the buffer to a temporary directory passed by absolute path.#2019-11-2821:33borkdudein the intellij setup it's also working like this: the working dir is the file's dir: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#intellij-idea#2019-11-2821:33eraserhdWhich means the PR I made would not be useful in this case.#2019-11-2821:34borkdude@eraserhd you would of course set the cwd to the dir of the linted file, not the copied tmp file#2019-11-2821:35eraserhdYeah.#2019-11-2821:37borkdudebut yeah, using the path of the copied tmp file for resolving the config dir is a bit pointless#2019-11-2821:40borkdude@eraserhd https://github.com/flycheck/flycheck/blob/269237f6529a4ad7db5bbbc5a40c1f038accf3cd/flycheck.el#L4990#2019-11-2821:45eraserhdWell, adding a cd to the editor script definitely works.#2019-11-2821:46eraserhdI'm looking at the language-specific checkers in the flycheck org. If very few of them override that working-directory thing, then I'll just make that PR to Kakoune.#2019-11-2821:51eraserhdOK, there are a few, by global GitHub search - elsa, elixir, scons, android, credo.#2019-11-2821:51eraserhdActually, that seems like a small list, except elixir is important.#2019-11-2821:53borkdudeand why does elixir do that?#2019-11-2823:47eraserhdI don't know, but it appears to try to find the "mix directory", which is the project root.#2019-11-2900:07eraserhdSo it appears to be not elixir proper, but some people's overrides of flycheck-elixir? I'm going to do the research a bit more carefully now and write it up for Kakoune.#2019-11-2900:46eraserhdI think I've been misunderstanding something... the buffer default-directory isn't really buffer-specific, and it's just emacs current working directory?#2019-11-2900:51eraserhdOkay, it is buffer specific, but it isn't the immediate ancestor of the buffer's file.#2019-11-2908:35borkdudeif I log the current working directory to a file in clj-kondo, I do get the parent directory of the buffer's file#2019-11-3009:52robert-stuttafordhey @borkdude! does / will clj-kondo report on unused vars at all, e.g. after linting the whole classpath? like unused private vars, but also non-private vars. this isn't useful for libraries, but it's very useful for apps!#2019-11-3009:54borkdude@robert-stuttaford That requires seeing the entire project first and this is the reason why clj-kondo won't report it in the editor, since it could also result in false positives (have we seen all the things? do we know for sure? it's an open world...) But... you can use the analysis export and script it yourself: https://github.com/borkdude/clj-kondo/tree/master/analysis#unused-vars#2019-11-3009:54borkdudeAnother reason it's not reported in the editor is performance: we would have to load the entire cache for every editor action, which is costly#2019-11-3009:55robert-stuttafordok, that makes sense. that a script exists and i can use it is plenty good enough for me 👍#2019-11-3009:55borkdudeThere have been some thoughts about making a cider middleware that invokes clj-kondo on the classpath and then uses the analysis export to make squiggles, so an on-demand action. I'd like to see someone pick this up some time#2019-11-3009:56borkdude@robert-stuttaford Yes, you can use clj-kondo as a JVM library as well and do fun things with the output#2019-11-3009:58robert-stuttafordthanks, this is rad 🙂#2019-12-0111:39borkdudeThere is a new way to run clj-kondo in IntelliJ now: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#lsp-server#2019-12-0120:54borkdudeinteresting idea from a convo with @souenzzo : libraries could at startup emit some piece of EDN config to a designated directory. e.g. .clj-kondo/libs/clara.rules/config.edn something for the hammock#2019-12-0310:04p-himikThe highlighting seems a bit different with the LSP server. Notice how the locals are highlighted along with the adjacent bracket. But the underlining is correct. Is it something that could be fixed on clj-kondo's side, or is it an issue with LSP?#2019-12-0310:05borkdudeThis is probably the plugin. clj-kondo is unaware of the editor it's used in#2019-12-0310:09borkdudeI'm not too familiar with the plugin itself. I don't even know how to build it: https://github.com/gtache/intellij-lsp/issues/122#2019-12-0310:10borkdudeBut I think it's possible to build a standalone IntelliJ plugin from it. So if there will be someone stepping up and tweaking the necessary stuff, it can be a better experience maybe. And there can be a clj-kondo IntelliJ extension in the Jetbrains marketplace#2019-12-0314:19Ian Fernandezhello, I'm running into linter error, but I don't understand why,
can't parse name_of_file.clj, no conversion to symbol
#2019-12-0314:20Ian Fernandezsomeone here can give me a hint?#2019-12-0314:23borkdude@d.ian.b can you give more context?#2019-12-0314:24borkdudecan you make a repro?#2019-12-0314:25Ian FernandezI'm running:
clj-kondo --lint src --config '{:output {:format :json}}' 
into a repository
#2019-12-0314:25Ian Fernandezthe linter is accusing this can't parse for every file on the repository#2019-12-0314:26Ian Fernandezand joker does not give me any error#2019-12-0314:28borkdude@d.ian.b can you make a repro that I can run locally? using the information you gave me I still can't reproduce it#2019-12-0314:28borkdudewhat version of clj-kondo are you running? what OS?#2019-12-0314:29Ian Fernandezclj-kondo version: 2019.11.23-1#2019-12-0314:30Ian FernandezOS, both in ubuntu and manjaro#2019-12-0314:30borkdudethe can't parse error is thrown here: https://github.com/borkdude/clj-kondo/blob/2889dff5f3a1d5691ca17e81ab33d624a3376d3d/src/clj_kondo/impl/analyzer.clj#L1479#2019-12-0314:31Ian FernandezI'll see here this#2019-12-0314:31borkdudeI don't know where the -1 comes from in the version. I didn't release that: https://github.com/borkdude/clj-kondo/releases#2019-12-0314:32dharriganIt's from the packager, arch in particular#2019-12-0314:32dharrigani.e., the pkgrel#2019-12-0314:32dharriganit's only for the OS, has no relation to what you have released 🙂 which is 2019.11.23#2019-12-0314:33borkdude@d.ian.b Try to narrow down the issue by linting only one file from the directory.#2019-12-0314:33borkdudeAnd run with CLJ_KONDO_DEV=true that might give you some more info#2019-12-0314:34dharriganIt's useful if the package meta around the release has changed, i.e., maybe a new depends or arch or url, but the underlying version of the package is the same, i.e., if you where to change the URL to ' then I would change the pkgrel to 2, but keep the pkgver to 2019.11.23, so then what would be installed would be 2019.11.23-2#2019-12-0314:34dharrigan🙂#2019-12-0314:36borkdude@d.ian.b and if possible, try to isolate the case to the smallest piece of code that still triggers the error for you and post it here.#2019-12-0314:36Ian FernandezI'll try this#2019-12-0314:57borkdude@d.ian.b Do you get the same error when you try to lint an empty file, e.g. put an empty file src/foo.clj in your project#2019-12-0314:57borkdudeand then run clj-kondo --lint src/foo.clj#2019-12-0314:58Ian Fernandezwill try#2019-12-0315:00Ian Fernandezit passes =<#2019-12-0314:58Ian FernandezI couldn't reproduce the error =<#2019-12-0314:58Ian Fernandezwill try#2019-12-0315:00Ian Fernandezit passes =<#2019-12-0315:01borkdudeso the error is gone now?#2019-12-0315:02Ian Fernandezno#2019-12-0315:03Ian Fernandezfoo does not in the error#2019-12-0315:03Ian Fernandezbut other namespaces are in error#2019-12-0315:03Ian Fernandezevery one another#2019-12-0315:03Ian Fernandezevery file#2019-12-0315:03borkdudecan you paste code from such a file into foo.clj and then see if that produces the error?#2019-12-0315:04borkdudeand if so, remove some code, lint again, until you see no error, and paste the smallest bit of code that still produced the error#2019-12-0317:29Ian Fernandezit happens when I add (ns folder.foo)#2019-12-0317:30Ian Fernandezsrc/folder/foo.clj:0:0: error: can't parse src/folder/foo.clj, no conversion to symbol#2019-12-0317:30borkdudelet me try#2019-12-0317:31Ian FernandezI have deps.edn src/folder/foo.clj#2019-12-0317:31borkdudeseems to work just fine here:
$ clj-kondo --lint - <<< '(ns folder.foo) (inc)'
<stdin>:1:17: error: clojure.core/inc is called with 0 args but expects 1
linting took 10ms, errors: 1, warnings: 0
#2019-12-0317:32Ian Fernandezclj-kondo --lint - <<< '(ns folder.foo) (inc)' <stdin>:0:0: error: can't parse <stdin>, no conversion to symbol linting took 4ms, errors: 1, warnings: 0#2019-12-0317:32borkdudecan you try with:
CLJ_KONDO_DEV=true clj-kondo --lint src/folder/foo.clj
#2019-12-0317:32borkdudecan you also type:
clj-kondo --version
#2019-12-0317:33Ian FernandezCLJ_KONDO_DEV=true clj-kondo --lint src/folder/foo.clj src/folder/foo.clj:0:0: error: can't parse src/folder/foo.clj, no conversion to symbol linting took 4ms, errors: 1, warnings: 0#2019-12-0317:33Ian Fernandezclj-kondo v2019.11.23#2019-12-0317:34borkdudeCan you try the same command but from a new directory in /tmp, like mkdir -p /tmp/foo && cd /tmp/foo && CLJ_KONDO_DEV=true clj-kondo --lint - <<< '(ns folder.foo) (inc)'#2019-12-0317:34Ian Fernandezworked#2019-12-0317:34Ian Fernandezmkdir -p /tmp/foo && cd /tmp/foo && clj-kondo --lint - <<< '(ns folder.foo) (inc)' <stdin>:1:17: error: clojure.core/inc is called with 0 args but expects 1 linting took 8ms, errors: 1, warnings: 0#2019-12-0317:35Ian Fernandezdo you know why?#2019-12-0317:35borkdudeCan you move aside the configuration you have in .clj-kondo/config.edn to .clj-kondo/config.bak#2019-12-0317:35borkdudeif you have any#2019-12-0317:36borkdudeand then try linting your project again#2019-12-0317:36Ian Fernandezthat#2019-12-0317:36Ian Fernandezthe problem was my config.edn#2019-12-0317:36borkdudeah. I'll make an issue to better report the errors in the config#2019-12-0317:36Ian Fernandez{:lint-as {folder.test.integrant/with-system when-let}}#2019-12-0317:36Ian Fernandezthis was the config#2019-12-0317:37borkdudethe second symbol has to be fully qualified as well#2019-12-0317:37Ian Fernandezaaaw#2019-12-0317:37Ian Fernandezthanks!#2019-12-0317:38borkdudemade an issue for it: https://github.com/borkdude/clj-kondo/issues/640#2019-12-0317:39Ian Fernandezthanks#2019-12-0315:09Ian FernandezOK, I'll try =)#2019-12-0316:52andrea.crottiI wonder if something like (def x (function-call ...)) should be linted#2019-12-0316:53andrea.crottithe amount oif hours wasted because of weird behaviours of things that should have been a defn but were a def is incredible#2019-12-0316:54andrea.crottiand they are usually bugs that only happen after a while in specific conditions, so if it's not actually a "simple" constant, should you really use def?#2019-12-0317:01borkdude@andrea.crotti I do that quite often#2019-12-0317:02borkdudeat least, I think I do. I'll keep it in mind#2019-12-0317:02andrea.crottiwell in many cases it's safe to do so#2019-12-0317:02borkdude
(def init-in (fn []
               #?(:clj (-> (.StringReader. "")
                           clojure.lang.LineNumberingPushbackReader.))))

(def init-out (fn [] (new #?(:clj .StringWriter
                             :cljs goog.string/StringBuffer))))

(def init-err (fn [] #?(:clj (.StringWriter.))))

(def in (vars/dynamic-var '*in* (init-in)))

(def out (vars/dynamic-var '*out* (init-out)))

(def err (vars/dynamic-var '*err* (init-err)))
#2019-12-0317:02andrea.crottibut when it's not you can end up with some really weird bugs#2019-12-0317:03andrea.crottiI was taking more about things like (def truncate-db (jdbc/execute conn "TRUNCATE TABLE x"))#2019-12-0317:03andrea.crottiwhich in this case it's clearly a problem of course, but it's not always so clear#2019-12-0317:04borkdudeyeah, it's quite impossible to know when it's not intended I think#2019-12-0317:06andrea.crottiyeah it's tricky#2019-12-0317:45Ian Fernandez@borkdude could you do some linting for hodur files?#2019-12-0317:45Ian Fernandezhaha#2019-12-0317:45Ian Fernandezit's another request 😃#2019-12-0318:13borkdudewhat is hodur?#2019-12-0318:34dominicmI'd guess https://github.com/hodur-org/hodur-engine#2019-12-0318:34dominicmthere was a talk on it at Clojutre#2019-12-0318:35borkdudeI need examples of what's currently not linted correctly about this library in a Github issue. Input + current errors + expected solutions.#2019-12-0320:09Ian Fernandezok, I'll do it later! 😃#2019-12-0417:07borkdudeNew intermediate binary version for linting missing requires (like (foo/bar) and (reduce foo/bar ...) when there is no require for foo): Mac: https://7556-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.11.24-SNAPSHOT-macos-amd64.zip Linux: https://7555-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2019.11.24-SNAPSHOT-linux-amd64.zip Branch: missing-require Please report any false positives you will find.#2019-12-0417:08borkdudeI found one problem in project.clj where there are names like foo/bar used in the defproject macro. If this is a common problem with other macros, then I will probably have to support a similar config as unresolved-symbol.#2019-12-0417:59dominicmah yes, macros. They ruin everything.#2019-12-0417:59celwellHi, I have clj-kondo working from the command line, thanks; but I'm having trouble getting it to integrate with flycheck in emacs. I installed flycheck-clj-kondo from MELPA and have it required in my init.el, but the syntax checkers seem to be disabled.#2019-12-0418:01celwellOh, hmmm... maybe clj-kondo isn't properly on my path. It works in Terminal (macos) but is not available in M-x shell#2019-12-0418:02sogaiu@celwell i had trouble with flycheck at one point -- here are some brief tips that i wrote down once i got things working better: https://gist.github.com/sogaiu/5f93faa7cab1d08a1510d281cadb0b81#2019-12-0418:13celwellYay, I got it working. For future reference, this is what I added to my Emacs init.el:
(setenv "PATH" (concat (getenv "PATH") ":/usr/local/bin"))
(setq exec-path (append exec-path '("/usr/local/bin")))
#2019-12-0418:14sogaiucongratulations 🙂 i think the clj-kondo flycheck docs might benefit from some troubleshooting tips#2019-12-0418:15sogaiufor reference, i took the circuitous route of moving some PATH stuff to ~/.profile#2019-12-0418:15sogaiuand making other arrangements for .profile to be read in other shell-related init files#2019-12-0418:35borkdudePR welcome!#2019-12-0418:35borkdudeoh already one in progress I see 🙂#2019-12-0418:36sogaiuty, @celwell#2019-12-0419:06borkdudemerged#2019-12-0520:31dominicmIt doesn't look possible to analyse a string from the kondo api, is that correct?#2019-12-0520:38borkdude@dominicm you mean string instead of file?#2019-12-0520:39borkdudeyou can do so with (with-in-str "<your-code"> (clj-kondo/run! {:lint "-"}))#2019-12-0520:39dominicm:o crazy#2019-12-0520:39dominicmI've never seen with-in-str before, neat.#2019-12-0521:03borkdude@dominicm it's very handy for testing command line applications#2019-12-0521:10dominicmI just hooked up the analysis to my code formatter. We've got some very cool things going on here... I'm able to accurately match defn.#2019-12-0521:10dominicmWell, accurately as kondo... :)#2019-12-0521:10borkdude😄#2019-12-0521:11dominicmSo many ~evil~ awesome things to do!#2019-12-0521:54dominicmInteresting, kondo doesn't detect (ns) as a var usage, should it?#2019-12-0521:55dominicm
(with-in-str "(ns foo)"
    (:analysis
      (kondo/run!
        {:lint ["-"]
         :config {:output {:analysis true}}})))
;; =>
{:namespace-definitions [{:filename "<stdin>", :row 1, :col 1, :name foo}],          
 :namespace-usages [],                                                               
 :var-definitions [],                                                                
 :var-usages []}         
#2019-12-0521:56borkdudeit reports it as a namespace definition#2019-12-0521:58borkdudethe ns macro is treated as a special case I guess#2019-12-0522:01dominicmHmm. Maybe I can special case detection then...#2019-12-0522:02borkdudeI don't object to adding it to the var-usages though#2019-12-0522:04dominicmOkay. May take a look :)#2019-12-0522:06sogaiuwill that lead to a removal from where it is already?#2019-12-0522:09dominicmI wouldn't think so. I think both are useful.#2019-12-0522:11sogaiutnx -- i just have code that depends on the current structure 🙂#2019-12-0522:21borkdudeno removal#2019-12-0522:21borkdudethe call might have some more detail to it, like the amount of arguments (which is pretty useless information for the ns macro probably)#2019-12-0522:22borkdudeand the namespace it was called from, but maybe that hints at the reason why it wasn't there in the first place#2019-12-0522:22borkdudebecause that place where it's called from is a bit of a grey area#2019-12-0522:25borkdudeso maybe it's fine as it is#2019-12-0522:26sogaiuthanks for the clarification#2019-12-0522:31dominicmIt's useful to me for identifying what it is. Not some other ns, the one and true ns.#2019-12-0522:36borkdudeBut are you interested in more than the location where ns was used?#2019-12-0522:43dominicmSorta. Kinda. I look at the arguments, like :require and manipulate them.#2019-12-0522:45borkdudeWe could maybe add that info to :namespace-definitions#2019-12-0607:48dominicmThen I have to look them up in a different place for ns.#2019-12-0607:49borkdudeBut using :require in ns is not a normal function call anyway ?#2019-12-0607:53dominicmThat's fine contextually :) all I need to know is whether the symbol is clojure.core/ns or not
#2019-12-0607:53dominicmCurrently I do that by cross referencing the location with the var usage data#2019-12-0607:54borkdudeIt is also reported there ?#2019-12-0607:58borkdudeSorry, not near a kbd, I’ll check on this later#2019-12-0607:59dominicmNo, that's what I reported yesterday...? I can derive the require once I'm inside ns, because that is contextual information#2019-12-0608:01borkdudeAh, I see. Like we discussed you can fall back on the location in namespace-definitions for now but feel free to add it. I think the ns form is called from the same namespace the ns form is called in conceptually #2019-12-0608:02dominicmYeah :) I will.#2019-12-0600:12celwellSecretary's defroute macro trigger's unresolved symbol ... . I assume this 'false positive' might come up with quite a few libraries that use a def* pattern, or any macro for that matter. Any ideas of what I can do, other than just trying to ignore it?#2019-12-0608:33borkdude@celwell it seems this pattern is co-incidentally a lot like clojure.core/defn:
$ clj -A:clj-kondo --config '{:lint-as {secretary.core/defroute clojure.core/defn}}' --lint /tmp/foo.clj
linting took 210ms, errors: 0, warnings: 0
(require '[secretary.core :as sec])

(sec/defroute home-path "/" [x] x)

(home-path 1)
#2019-12-0618:56celwellOooo... nice, I 'll use that, thanks!#2019-12-0614:03plexus👋:skin-tone-2:#2019-12-0614:04plexusis it possible to tell clj-kondo that for certain namespaces :refer :all is ok?#2019-12-0614:06borkdude@plexus There is an open issue for this: https://github.com/borkdude/clj-kondo/issues/560 It's not yet implemented.#2019-12-0614:06plexusok, thanks!#2019-12-0614:06borkdudeThere is a proposal in the issue and it might not be too hard to implement, so if you're interested, go for it.#2019-12-0614:07borkdudeOtherwise, I bumped the priority of the issue in the board, so hopefully it shouldn't be too long#2019-12-0614:07borkdudeIf you decide to work on it, please let me know, so I can set the issue in progress and assign a name to it#2019-12-0614:08plexusI'll let you know, I have an open PR on rep that I should probably wrap up before opening up new ones 🙂#2019-12-0614:09borkdudesure 🙂#2019-12-0619:58Nick McCurdyI’m getting unresolved symbol errors when using :refer :all (as generated by Leiningen’s test files). Is that expected or are they supposed to be hidden after this fix? I am on version 2019.11.23 <https://github.com/borkdude/clj-kondo/commit/7ee6199b93528701b2bfe5b7a8ddcbff96a0b956>#2019-12-0620:03borkdudeIf you also lint the referred namespace and use a project cache, clj-kondo will be able to resolve those syms #2019-12-0704:38Nick McCurdyThanks I forgot to run that part of the setup#2019-12-0704:38Nick McCurdyI’m enjoying Kondo so far 🙂#2019-12-0719:58erwinrooijakkersHi all#2019-12-0719:59erwinrooijakkersI use this config:
(use-package clojure-mode
    :ensure t
    :config
    (require 'flycheck-joker)
    ;; (require 'flycheck-clj-kondo)
    (dolist (checker '(clj-kondo-clj clj-kondo-cljs clj-kondo-cljc clj-kondo-edn))
      (setq flycheck-checkers (cons checker (delq checker flycheck-checkers))))
    (dolist (checkers '((clj-kondo-clj . clojure-joker)
                        (clj-kondo-cljs . clojurescript-joker)
                        (clj-kondo-cljc . clojure-joker)
                        (clj-kondo-edn . edn-joker)))
      (flycheck-add-next-checker (car checkers) (cons 'error (cdr checkers)))))
And get this warning: > Error (use-package): clojure-mode/:config: clj-kondo-clj is not a valid syntax checker
#2019-12-0719:59erwinrooijakkersHow to fix?#2019-12-0720:00borkdudeyou commented out require flycheck-clj-kondo, that's probably why?#2019-12-1016:03erwinrooijakkersNo doesn’t change the outcome…#2019-12-1016:04erwinrooijakkersSame error messages with or without#2019-12-1016:04erwinrooijakkersAnd I’ve added clj-kondo to additional packages like this:
dotspacemacs-additional-packages
   '(
     flycheck-joker
     flycheck-clj-kondo
     )
#2019-12-1016:05borkdudeis this spacemacs? probably better ask in #spacemacs, they're very helpful there and they know it better than I do#2019-12-1016:05erwinrooijakkersOk I will thanks!#2019-12-1016:05erwinrooijakkersyes spacemacs#2019-12-0813:56borkdude#2019-12-0909:11viestihohum, thinking out loud, would it be possible to have a linter that warns about unregistered multimethod implementations..#2019-12-0910:07viestiSince now, there might be a case where a required namespace is marked as unused, but is required because a multimethod is registered#2019-12-0910:09borkdude@viesti In that case you should just not use an alias for the namespace and then clj-kondo will ignore it#2019-12-0910:10viestiah, true#2019-12-0910:59yuhanI've been playing around a bit with clj-kondo's type checker and found a few 'bugs' I wasn't sure were intentional#2019-12-0911:01borkdudefeel free to post them#2019-12-0911:01yuhanpeek and pop are specced as taking vectors only whereas they actually take lists just fine#2019-12-0911:02borkdudeok, that can be fixed#2019-12-0911:02yuhanDoes the type system support union types?#2019-12-0911:02borkdudefeel free to post an issue#2019-12-0911:03borkdudeyeah, you can do something like #{:list :vector}#2019-12-0911:03yuhannice, I'll do a PR soon#2019-12-0911:04yuhanthere are also lots of predicate any->boolean core functions that aren't specced yet, is it just incomplete or are there some performance costs to having a larger database?#2019-12-0911:05borkdudejust incomplete#2019-12-0911:07yuhanIs it right to say that nil is always Associative? I can't think of a core function on maps that doesn't accept nils.#2019-12-0911:09borkdudewhat's the background of that question?#2019-12-0911:09yuhanright now there seem to be a mix of :nilable/associative and :associative in the database#2019-12-0911:09borkdude
(merge nil {})
(assoc nil 1 2)
are both accepted by clj-kondo
#2019-12-0911:09yuhan(dissoc nil 1) isn't#2019-12-0911:10yuhanor (select-keys nil [])#2019-12-0911:10borkdudeah#2019-12-0911:11yuhanand I was wondering if they could be simplified to a single type#2019-12-0911:11borkdudeI'm not sure what would be the consequence of spec'ing nil as associative#2019-12-0911:11borkdude
user=> (associative? nil)
false
#2019-12-0911:11yuhanah#2019-12-0911:12borkdudeso I guess all of those have to be spec'ed as nilable/associative#2019-12-0911:15yuhanthe nilable return types don't seem to be currently propagated anyway#2019-12-0911:16yuhan(dissoc (merge) 1) doesn't show an error although merge returns nilable#2019-12-0911:17borkdudethis is because merge could also have returned a map.#2019-12-0911:17borkduderelying on empty colls or nils in clojure is often an implementation detail#2019-12-0911:18yuhanyeah, but it's broader than the (currently incorrect) input spec of dissoc#2019-12-0911:18borkdude
(clojure.set/union)
#{}
#2019-12-0911:18yuhaneg. I haven't tried it out yet, but given a function f that was specced as {:ret nilable/number}#2019-12-0911:19yuhan(inc (f)) should be a type error#2019-12-0911:19borkdudethat's not true, since f could have returned a number, this code could be correct.#2019-12-0911:20borkdudeoften this relies on the input values of f#2019-12-0911:20borkdudeand the knowledge of the programmer who uses f in such a way that this is correct#2019-12-0911:20borkdudeclojure isn't statically typed#2019-12-0911:20yuhanhmm, alright - I guess this makes sense from the perspective of a dynamic language#2019-12-0911:21borkdudeclj-kondo only gives type errors when it knows for sure there will be an error#2019-12-0911:21yuhanI was thinking it would be a great way of spotting potential places where null pointer exceptions could occur#2019-12-0911:21borkdudee.g. (inc "foo") will never be correct, since a string can never be a number#2019-12-0911:22borkdudemaybe that's more a job for core.typed#2019-12-0911:23borkdudeif you want to have such checks, you will have to convince the type checker that (f) will return a number, but often these checks rely on (if (number? (f)) (inc (f)) in dynamic code#2019-12-0911:23borkdudeit could be that CLJS already has this kind of type inference, but the type system in clj-kondo is pretty basic and does not attempt to resolve using occurrence typing#2019-12-0911:24borkdudeit might have one day, the type checker is pretty new#2019-12-0911:24borkdudebut for now it's better to err of preventing false positives#2019-12-0911:26yuhanGot it, thanks for the explanations! Type theory and tooling is such a huge space to cover#2019-12-0911:27borkdudethe implementation is pretty straightforward: https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/types.clj#L42 any x that could be an y, will be considered as an y to satisfy the spec#2019-12-0911:36yuhanlast thing for now - what's the rationale behind the :seqable-out type?#2019-12-0911:38yuhanthe few functions that are specced with return types of :seqable-out like map keep always return lazy seqs, unless I'm mistaken#2019-12-0911:46borkdude@qythium seqable-out doesn't include nil, whereas seqable does. so you should not rely on seqable-out being a nil, that's the point of it#2019-12-0911:46borkdudeif you include nil in seqable-out, then a lot of type warnings won't work anymore#2019-12-0911:49borkdudeI have some notes on it here:
** why seqable-out?
If we would make seqable functions to return a seqable, that would include
string and would turn this warning off:

$ clj -A:clj-kondo --lint - <<< '(defn foo [^String _x]) (foo (next [1 2 3]))'
<stdin>:1:30: warning: Expected: string or nil, received: seqable collection.
#2019-12-0911:49borkdudeoh so it was more about the string than nil I guess#2019-12-0911:49borkdudeseqable? is a bit of an odd predicate, it includes nil and strings, that's why I have a seperate one#2019-12-0911:51borkdudeit's also about nil, because (next ..) could return nil (since nil is seqable) and then nilable X are satisfied as well, regardless of what X is#2019-12-0911:52yuhanbut functions like map and filter will never return any seqable other than a seq#2019-12-0911:53yuhanso eg. (peek (map ...)) should be a type error, whereas it currently thinks map could return a vector#2019-12-0911:57borkdudeyeah you should not rely on any of the seq functions to return a vector, so this is something we need to look at#2019-12-0912:03borkdudefeel free to post that in an issue with the other findings you have#2019-12-0912:11yuhanah I was planning to submit a PR directly, I hope that's okay#2019-12-0912:11borkdudefor the nilable/associative stuff that's fine.#2019-12-0912:12borkdudeplease compare the output of .circleci/script/performance in your PR branch to the one on master for any regressions#2019-12-0912:14borkdudeautomating that somehow would be nice, so a diff of that script output would show up in the PR, but that's another issue 😉#2019-12-0912:15borkdudeI check the output of that script for any differences in linting output#2019-12-0912:15borkdudeIt lints a bunch of libraries (clojure, clojurescript, cheshire, etc)#2019-12-0912:19borkdudehttps://github.com/borkdude/clj-kondo/issues/643#2019-12-0913:46yuhanIs that supposed to be run locally? I tried executing .circleci/script/performance and it resulted in find: ./clj-kondo: No such file or directory errors#2019-12-0913:46borkdudeit runs the locally compiled binary#2019-12-0913:47borkdudein the current directory#2019-12-0913:47borkdudebut you can also just download the result from circleci once you made a branch / PR#2019-12-0913:47borkdudeI usually do the latter#2019-12-0913:49yuhanI've never worked with circleci before, so I have to actually create the PR first?#2019-12-0913:50borkdudeI don't think so actually#2019-12-0913:50borkdudeif you push your branch to github and then go to https://circleci.com/gh/<your-user-name>/clj-kondo I think you should see something#2019-12-0913:51borkdudemaybe you have to click on it once to "follow" the project#2019-12-0916:47Marc O'Morain❤️ @borkdude you just saved me hours of debugging
{:keys [state pc input] :as state}
        ~~~~~ unused binding state
#2019-12-0916:48Marc O'MorainI had one binding shadow another#2019-12-0922:34borkdude@qythium I think I would prefer multiple smaller PRs instead of one big PR for the type annotations#2019-12-0922:34borkdudeSince we already discussed the nilable/associative thing, that would be a trivial change#2019-12-0922:34borkdudeOther changes might be less trivial#2019-12-1003:26yuhansure - I was still figuring the CircleCI stuff out last night, will try again later#2019-12-1017:41erwinrooijakkersHow could we remove warnings like these again?#2019-12-1017:41erwinrooijakkers#2019-12-1017:41erwinrooijakkersAdding defstate in some .clj-kondo right#2019-12-1017:42erwinrooijakkershttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md#2019-12-1017:42erwinrooijakkers{:lint-as {mount.core/defstate clojure.core/defn}}#2019-12-1017:43erwinrooijakkersIn .clj-kondo/config.edn#2019-12-1017:44erwinrooijakkersWould be nice if a tool went over your libraries and added all the macros configs to config.edn#2019-12-1017:49borkdude@erwinrooijakkers You can write such a tool using the analysis output: https://github.com/borkdude/clj-kondo/tree/master/analysis#2019-12-1017:54erwinrooijakkersCan you explain in one line what extra step is needed after running the analysis on a project? 🙂#2019-12-1017:58borkdudeselecting all the macros from the analysis output and stuff them in your config file#2019-12-1018:20mafcocincoI'm a newb to clj-kondo. Trying to get it setup in my Spacemacs configuration. I have followed the steps as they appear here: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#spacemacs for the master branch, but to no avail. I'm reasonably confident that clj-kondo is available on my emacs path as I can run it from a shell that I start in emacs (Not sure if this is a sufficient test or not). I was able to build the cache in a .clj-kondo directory within the project I'm working on and could run the linter from the CLI without issue. However, getting clj-kondo working inside of Emacs is the last and most important step. Thanks in advance!#2019-12-1018:24borkdude@mafcocinco Have you tried this? https://github.com/borkdude/flycheck-clj-kondo#troubleshooting#2019-12-1018:31mafcocincoI have not. I will give it a try! Thanks.#2019-12-1019:03mafcocincoclj-kondo-clj appears to be configured correctly. It could be that my expectations are off or user error is manifesting in some other way. The .clj-kondo cache is built for this project and I was able to lint files from the CLI. It was my expectation that if I included an unused namespace, for example, clj-kondo (if configured properly) would underline the namespace and flag it as unnecessary. That is currently not happening but maybe there is something else I need to do to turn this functionality on.#2019-12-1021:11borkdude@mafcocinco I think it should say: Flycheck Mode is enabled. Use C-u C-c ! x to enable disabled checkers.#2019-12-1021:49mafcocincothat did it. thanks @borkdude!#2019-12-1202:28Aleedwhy is the following snippet giving me an unresolved symbol error for the {:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "8ef0ceeffce9fd"}, :content ("[email protected]")} declaration?
(defn example
  [name]
  `(defmacro ~name [& args#]
     `(foo ~(keyword '~name) 
#2019-12-1208:17borkdude@alidcastano Because the author did not know that syntax-quotes are allowed to be nested#2019-12-1208:22borkdudeFeel free to post an issue#2019-12-1214:26teawaterwirehow to tell kondo it's ok?#2019-12-1214:27borkdude@teawaterwire what version of clj-kondo are you using and which editor / plugin?#2019-12-1214:45teawaterwiresorry yes more details: vscode with calva it's on clojurescript code i'm tagging a symbol to be treated as js#2019-12-1214:46borkdudeis it only a .cljs file or maybe a .cljc file?#2019-12-1214:46teawaterwireonly cljs#2019-12-1214:46borkdudeif you can give a repro using a small code snippet, that would be helpful#2019-12-1214:48teawaterwireyes trying to isolate a simple snippet#2019-12-1214:53teawaterwirei tried this mini-snippet#2019-12-1215:08borkdudecan you please just paste the code instead of screenshots? then I can repro it myself#2019-12-1215:09borkdudenever mind, (.log js/console ^js #js [1 2 3]) is enough to reproduce it#2019-12-1215:10borkdudeI'll make an issue for it. meanwhile you can add this symbol to your .clj-kondo/config.edn config#2019-12-1215:10borkdudeDetails see: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#2019-12-1215:12borkdudehttps://github.com/borkdude/clj-kondo/issues/647#2019-12-1215:37teawaterwiresorry for the screenshot thank you for the answer!#2019-12-1215:38borkdudenp#2019-12-1214:27borkdudeand please give some more context, repro using text instead of a screenshot#2019-12-1214:41mafcocincoQuestion regarding HugSQL but I think it speaks to a more general (potential) issue: I'm not sure if anyone has used HugSQL, but it dynamically defines clojure functions based on a markup syntax within the comments of an SQL file. As one might imagine, clj-kondo has no context/understanding that these functions exist (they are generated by loading the SQL file with a function that HugSQL provides). Any thoughts on how to handle HugSQL specifically and, perhaps more importantly, how to handle dynamically generated functions (i.e. functions that are produced via calls to eval, etc.)?#2019-12-1214:42borkdude@mafcocinco see https://github.com/borkdude/clj-kondo/blob/master/doc/config.md, hugsql is mentioned there#2019-12-1214:43mafcocincoCool, makes sense as the declare call will introduce the symbol in a context that clj-kondo knows about. Clever solution. Thanks.#2019-12-1214:44borkdudeI'm also using hugsql myself and this is how I do it as well#2019-12-1214:46mafcocincoYeah, I generally have a wrapper clj file that should be included to use the hugsql functions, which avoids redundant declarations of the functions. Would be easy to add the declare statements in those files. Also has the side benefit of surfacing the names of the functions that the SQL file provides without the user having to dig into the SQL file.#2019-12-1214:47borkdudeI found that helpful too#2019-12-1220:45avi👋 is this a known issue or am I doing something weird here, or just missing something?
;; clj-kondo is warning about this first line: warning: unused binding alias-sym
  (doseq [[ns-sym _ alias-sym] (cons t ts)]
    (create-ns ns-sym)
    (alias alias-sym ns-sym))
I’m using v2019.11.23 with the default config.
#2019-12-1220:46borkdudenot wrong, probably a bug in the analysis of alias, sorry 🙂#2019-12-1220:47borkdudeusually alias is called with a literal symbol, that's why it didn't show up before#2019-12-1220:47aviAha! no worries. I’ll open an issue. Thank you!#2019-12-1220:47borkdudebtw, I enjoyed your talk on fc4#2019-12-1220:53avioh, thanks! That’s great to hear! 😊#2019-12-1220:53avihttps://github.com/borkdude/clj-kondo/issues/649#2019-12-1220:53aviThanks for clj-kondo!#2019-12-1220:54borkdudenp!#2019-12-1318:05geraldodev@borkdude clara has this ?binding syntax on defrule macro. In the 1st case its a binding . the second one is a comparison (since the binding already exist). Misspelling the ?cd_paciente binding cause wrong projection, because you have two bindings and no comparison. Could clj-kondo be used to warn ununsed binding ?#2019-12-1322:40borkdudeNot as it is right now I think. You can however disable linting for clara so it won't give any false positives: https://github.com/borkdude/clj-kondo/issues/576#2019-12-1412:23borkdude@qythium You can re-run your PR using the following: Go to https://circleci.com/gh/yuhan0/clj-kondo/27 and press "Rerun workflow" Meanwhile I've added some notes on PRs here: https://github.com/borkdude/clj-kondo/blob/master/doc/dev.md#pr#2019-12-1413:07yuhanPressing "rerun workflow" still results in the same error#2019-12-1413:08borkdudecan you merge with master and push that?#2019-12-1413:10yuhanIt has to be a force-push, is that alright?#2019-12-1413:10borkdudewhy does it have to be a force push?#2019-12-1413:10yuhanoh sorry, I rebased on master instead of merging#2019-12-1413:10yuhanhang on#2019-12-1413:11borkdudeI think CircleCI gets confused when you force push a commit when another is still running, or something along those lines#2019-12-1413:12borkdudePushing a totally new commit should fix it#2019-12-1413:14yuhanMaybe I'm missing something, but I could only get my branch to run on Circleci by editing the yml config file and pushing a temporary commit#2019-12-1413:14yuhanthe force push was to remove that commit after making the PR, sorry about the trouble it caused#2019-12-1413:18yuhansame error.. should I make a new branch and try opening another PR?#2019-12-1413:18borkdudeyeah, let's just do that#2019-12-1413:21borkdudebtw, the spec for get is obviously wrong if you look at https://github.com/clojure/clojure/blob/653b8465845a78ef7543e0a250078eea2d56b659/src/jvm/clojure/lang/RT.java#L758 anything may implement the ILookup interface, that's why it's spec'ed as ::any in speculative: https://github.com/borkdude/speculative/blob/master/src/speculative/core.cljc#L202#2019-12-1413:24yuhanah, my mistake#2019-12-1413:24yuhanshould I change it to :any or remove the commit altogether?#2019-12-1413:24borkdudemaybe make a note there, so it will be left untouched#2019-12-1413:25borkdudekeys nilable associative is also wrong since (keys (filter ... {:a 1})) works#2019-12-1413:25borkdudethat's why it's seqable#2019-12-1413:26borkdudeso only the x -> nilable/x things are good to add I think#2019-12-1413:26yuhanhmm, alright#2019-12-1413:27borkdudeyeah, it's complicated. the specs in speculative already dealt with a lot of examples from the wild, so its good to look at those first#2019-12-1413:27yuhanokay#2019-12-1413:27yuhanso like the type system isn't strong enough to capture those functions#2019-12-1413:27yuhanshould get be left unspecced then? since it's essentially an any->any function#2019-12-1413:28borkdudeyes#2019-12-1413:29borkdudethe type of keys is Seqable[MapEntry] if you would have higher kinded types#2019-12-1413:29borkdudebut we don't have that, it's a pretty weak typesystem that only screams at you if something is clearly wrong#2019-12-1413:34yuhanalright, pushed with comments#2019-12-1413:36borkdudeDid you do any changes to .circleci/config.yml? I think that might be the reason why the JVM tests aren't passing#2019-12-1413:36yuhannot on the PR branch#2019-12-1413:38borkdudenormally the script looks at CIRCLE_PR_USERNAME, but somehow that's not set#2019-12-1413:39borkdudefor example, if you look at another PR: https://github.com/borkdude/clj-kondo/pull/651 it just works#2019-12-1413:40borkdudemaybe you should try to unfollow the project on circleci again, because it seems the project isn't running the PR branch under my name#2019-12-1413:40borkdudeconfusing, this#2019-12-1413:42yuhanyeah sorry, it's my first time on circleci and I might have messed things up without knowing how#2019-12-1413:43borkdude@U0K592YDP it seems like his PR isn't running on my account somehow: https://circleci.com/gh/borkdude/clj-kondo#2019-12-1413:45borkdudealso it seems his macOS step isn't running#2019-12-1413:47yuhanI think that was because I'm on the free plan and macOS jobs are only for paid plans#2019-12-1413:49borkdudeI'm also on the free plan#2019-12-1413:52borkdude@qythium can you delete clj-kondo from your circleci account and then do another commit?#2019-12-1413:53borkdude(dummy commit to re-trigger circleci)#2019-12-1413:53yuhanI've already "unfollowed" the project, is deleting a separate thing?#2019-12-1413:53borkdudenot sure#2019-12-1413:57borkdudeit seems like it's now correctly building#2019-12-1413:58borkdudeso I probably gave the wrong tip of following the project#2019-12-1414:05yuhanInteresting, but that would make it complicated for contributors to run and test things like the performance script on their end without opening a PR#2019-12-1414:06yuhanor creating a local Docker container and running Circleci there, from what I gathered#2019-12-1414:12yuhanActually my main motivation for looking into clj-kondo's type checker was to have it warn me about using get on vectors that had accidentally been converted to lazy seqs - I found myself making that error a few times resulting in hard-to-trace bugs because it would propagate nils silently#2019-12-1414:12yuhanIt's good to know that I can choose to override it at a local config level, even if :associative is technically too narrow#2019-12-1414:59borkdudeyeah#2019-12-1415:00borkdudeas a last step (and I hope you're not getting annoyed now): it would be good to add a couple of unit tests for the things you changed, so they will lock down the changes you made#2019-12-1415:19borkdudepushed a test myself now#2019-12-1415:22borkdudemerged#2019-12-1415:27yuhanoops, only just saw this#2019-12-1415:27yuhanthanks for your time! I wasn't annoyed at all :)#2019-12-1415:28borkdudeand thank you for your contribution 🙂#2019-12-1412:23borkdudeAnd I've added a script in script/diff which you can use to detect regressions#2019-12-1412:38kwrooijenHey, is it possible to add linter configuration to a library? For example I have my main project, and a library, If I add this to my main-app/.clj-kondo/config.edn it works. But if I add it to my-lib/.clj-kondo/config.edn , and then add my-lib to the dependencies of main-app it doesn’t work. I couldn’t find it in https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#2019-12-1412:39borkdudeThere is an issue for this: https://github.com/borkdude/clj-kondo/issues/559 Please read it and feel free to share your thoughts there#2019-12-1412:40kwrooijenThanks! I’ll take a look#2019-12-1413:00borkdudeI now included a Github action that diffs linting changes to a branch and master: https://github.com/borkdude/clj-kondo/commit/54977287ef7897af9260844fde19d211d42fa8e8/checks?check_suite_id=358386407#2019-12-1421:30borkdudeClj-kondo v2019.12.14 Unresolved namespace linter and 13 other enhancements/fixes! This might be the last release for 2019. Thanks you all for the great feedback and contributions. https://github.com/borkdude/clj-kondo/releases/tag/v2019.12.14#2019-12-1601:58ericdalloUpdating on Nix 😃 : https://github.com/NixOS/nixpkgs/pull/75733#2019-12-1817:15erwinrooijakkersThank you!#2019-12-1619:27borkdude@delaguardo I'm getting these 403s from the clojure lint action: https://github.com/borkdude/clj-kondo/pull/665/checks?check_run_id=351219419#2019-12-1619:27borkdudeAny idea what's going on?#2019-12-1708:34delaguardoAccording to documentation create-check-run should not be triggered from the push to the branch in a forked repository. Will try to find a workaround#2019-12-1620:05delaguardoCan't check right now. Already away from the keyboard. Will check that tomorrow morning.#2019-12-1620:09borkdudeno hurry 🙂#2019-12-1620:22mandersonAny suggestions on how best to handle linter errors/warnings when using next.jdbc/with-transaction ? One would think to lint-as clojure.core/with-open, however this doesn’t work because with-transaction supports an odd number of arguments in the initial vector and so you get uneven forms error. Example usage:
(next.jdbc/with-transaction [conn datasource options-map]
  ;; do stuff with conn
  )
#2019-12-1620:42borkdudehmm, maybe just ignore the name conn with {:linters {:unresolved-symbol {:exclude [(next.jdbc/with-transaction [conn])]}}}#2019-12-1620:42borkdudeand if that's not sufficient, ignore all symbols by just leaving out the vector#2019-12-1620:46mandersonHa, great minds! Looked away from Slack to read your documentation more and landed on this same approach 🙂 Thanks for the help and for a great tool!#2019-12-1620:49borkdude👍#2019-12-1718:01ericdalloHi @borkdude, can I use clj-kondo.lsp(https://github.com/borkdude/clj-kondo.lsp) with lsp-mode (https://github.com/emacs-lsp/lsp-mode) on emacs?#2019-12-1718:21borkdude@ericdallo should be possible I think, although I didn't test it. Here are the instructions for IntelliJ LSP: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#lsp-server#2019-12-1718:22borkdudeIf you figure this out, some docs would be nice 🙂#2019-12-1718:22borkdudeWhy are you interested, does the binary not work for you?#2019-12-1718:27ericdalloCool, I was just wondering if I can use clj-kondo with a different UI than flycheck, like lsp-ui , i think that just with lsp-mode i can achieve this, right?#2019-12-1718:27borkdudeI think so yes#2019-12-1718:28borkdudeIt works in VSCode and IntelliJ with the same server#2019-12-1719:20ericdalloNice, I will give a try configuring this on emacs and notice you if it work, thanks!#2019-12-1723:44ericdallo@borkdude Currently lsp-mode only supports clojure-lsp (https://github.com/snoe/clojure-lsp) as a clojure LSP, but we can open a PR adding clj-kondo as another option(like other lsp languages already do, like rust and c++). I created a bash script with java -jar clj-kondo-lsp-server.jar and just changed my lsp-mode to point to this script and it works! parrot#2019-12-1807:43borkdudeawesome!#2019-12-1817:56borkdude@ericdallo Maybe you could provide some docs how to set this up as part of https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md, if you like#2019-12-1818:32ericdallototally, one thing that we should do, its package a binary for the lsp-server, like clojure-lsp already does(https://github.com/snoe/clojure-lsp/releases), which this, we only need to point to this binary on the lsp-mode configuration and I can provide some docs how to do it. I don't know if we can run the lsp-server on lsp-mode from a jar, (I tried with no success :/) , maybe yes if we change lsp-mode here(https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-clojure.el#L141) allowing one more lsp for clojure, the clj-kondo, like the docs recommend here(https://github.com/emacs-lsp/lsp-mode#registering-server). What you think @borkdude?#2019-12-1819:10borkdude@ericdallo What about just documenting what you did: make a wrapper script that calls java -jar ... and register that wrapper script with lsp-mode?#2019-12-1819:11borkdudeIt may not seem optimal, but for now it might be the best we have, and we can make it more polished if more people start using this?#2019-12-1819:11ericdalloYeah, i think its a good start, i will write the docs and open the PR 🙂#2019-12-1819:13borkduderegistering "java -jar ..." directly with lsp-mode didn't work?#2019-12-1822:11ericdalloit was my first try, but it didn't work, but i tested again pointing to the full path of the jar (not *~/*the/path/to/jar) and worked! I guess a documentation on clj-kondo.lsp's README teaching just to set the lsp-clojure-server-command to run a java -jar ... its good enough partywombat#2019-12-1822:15borkdudeYeah, or in the editor integration like there are docs for IntelliJ#2019-12-1822:22ericdalloMaybe on both, what do you think?#2019-12-1822:23borkdudeI think it makes sense to include it in the clj-kondo repo and then I could link to it from the .lsp repo#2019-12-1822:24borkdudehttps://github.com/borkdude/clj-kondo/tree/master/doc/editor-integration.md#2019-12-1822:51ericdallohttps://github.com/borkdude/clj-kondo/pull/668#2019-12-1822:51ericdalloThanks @borkdude, I will try to use clj-kondo as a lsp server on emacs, and I can report the issues/improvements later#2019-12-1822:51borkdudeThank you very much#2019-12-1823:41ericdallo@borkdude Do you know if its hard to start implementing lsp features on clj-kondo.lsp like rename, references and completion, similar how clojure-lsp (https://github.com/snoe/clojure-lsp/blob/943188e7c64e2a5d635e8f3424feb67a34f0bc79/src/clojure_lsp/main.clj#L120) does? I think that clj-kondo is awesome and powerful, with these lsp features, it would be wonderful! I would like to help implement, but i don't know how hard is and how to debug/test this as I implement? (PS: i don't know how LSP works, i know that its a message channel that expect specific headers and other things). I'm studyng lsp4j, that i saw that you used to work with LSP. I hope I can help in some way#2019-12-1910:04borkdudeInteresting idea. I'd like to make/see a tool that can both be used with the binary and the LSP server. There are some ideas for this here: Once this is there, as a JVM lib, it can be hooked up to the LSP server as well https://github.com/borkdude/clj-kondo/issues/253#2019-12-1910:05borkdude> This tool could potentially also fix some warnings by rewriting code. Maybe there has to be a separate issue for it btw.#2019-12-1912:33ericdalloIt looks like a good idea, i know that LSP has the code actions feature, where you can do some action at point, insert some code or replace a existent by something you choose, like create getters, setters and constructor in java. I think LSP can help with these#2019-12-1909:55helios@borkdude from what I am gathering from here (https://github.com/borkdude/clj-kondo/commit/56e9a51bf1c87276e4ff9c928f5207d89f90dab7) clj-kondo should ignore the comments. Does that include (comment xxx) ? Because i think i'm still getting warnings for stuff inside such comments.#2019-12-1909:56borkdude@helios a comment in rewrite-clj is something of the form ;;#2019-12-1909:56borkdudeclj-kondo does lint clojure.core/comment sections#2019-12-1909:56borkdudeyou can turn it off, read the config docs#2019-12-1909:57borkdudebut personally I find it very helpful#2019-12-1909:57heliosah ok didn't see it in the config yet, thank you 🙇#2019-12-1909:58borkdudeclojure.core/comment sections are often used as REPL buffers for experimentation, that is why I want linting there#2019-12-1909:58heliosI agree, but I introduced now a clj-kondo on a big project with a LOT of warnings. So i'm turning off everything ( 😄 ) until i get everything green. Then refactor stuff and re-enable it so it keeps being green#2019-12-1910:22dominicmI use reviewdog to handle this. It only warns for things not on master.#2019-12-1910:24helioswith clj-kondo ?#2019-12-1910:24heliosthanks for the tip, seems interesting as well 😄#2019-12-1913:29dominicmYeah#2019-12-1909:58borkdudeok that makes sense. what you can also do is lint the current stuff to a status-quo.txt file and then view the diff between new changes and that file#2019-12-1909:59heliosah, interesting idea as well#2019-12-1909:59borkdudethis is what I do myself in clj-kondo with new linters or changes to linters, to detect regressions#2019-12-1909:59borkdudeyou can also leverage the EDN / JSON output for more intelligent diffing / nicer reports#2019-12-1910:01heliosI'll look into that. Also I've seen a very interesting GitHub action (https://github.com/marketplace/actions/clj-kondo-checks)#2019-12-1910:01heliosMaybe i'll add it to the README#2019-12-1910:01borkdudegood idea#2019-12-1910:02borkdudeMaybe a new page called Build integration or CI integration would be nice, so we can add more stuff there#2019-12-1910:02helios👍 will do that#2019-12-1910:17helios@borkdude something seems to not work with the github action (https://github.com/borkdude/clj-kondo/pull/669/checks?check_run_id=356139159 )#2019-12-1910:18borkdudeyeah, you can ignore that. it's something @delaguardo was looking into I think#2019-12-1910:18helios👍#2019-12-1910:18borkdudethat step doesn't work with pull requests somehow#2019-12-1910:19delaguardoOnly with PRs from forked repositories#2019-12-1910:19borkdude"CI integration" = "Continuous integration integration", maybe it's a bit double#2019-12-1910:20borkdudeDoesn't @helios have a forked repo?#2019-12-1910:20heliosI have a forked repo
#2019-12-1910:20heliosI understand that is a bit double, but you're integrating clj-kondo with their continuous integration process 😛 Maybe I can find a synonym#2019-12-1910:21borkdudeyeah, maybe it's fine as it is. I like it better than "Build integration" since CI is most often a remote thing whereas build can also be local#2019-12-1910:21borkdudefwiw this is the Github actions config: https://github.com/borkdude/clj-kondo/blob/master/.github/workflows/clj-kondo.yml#2019-12-1910:21borkdudeI'm not sure if anything's wrong there#2019-12-1912:50helios@borkdude thanks for managing overrides in a nice way. It was really good to create a ci-specific config.edn file and specify just the overrides for ci there 🙂 and keep the main clj-kondo config in the main config.edn file :thumbsup:#2019-12-1912:50borkdudeAh, maybe that's worth mentioning in the CI docs 🙂#2019-12-1912:56heliosWhy not 😄#2019-12-1913:12borkdude@helios Congrats on the ClojureD talk btw. See you there!#2019-12-1913:13heliosthanks! 😄 Yeah looking forward to it#2019-12-2020:33pezDoes clj-kondo have some way to tell a binding vector from other vectors? Or is it based on a list of known macros?#2019-12-2020:33pezAsking for a friend. 😃#2019-12-2020:58borkdude@pez What's the background of this question?#2019-12-2020:58pezThe background: https://github.com/BetterThanTomorrow/calva/issues/529#2019-12-2021:00borkdudeHow does this relate to linting?#2019-12-2021:01pezNot at all. I just notice that clj-kondo seems to know when I am not using bindings, and that paredit feature would neeed similar knowledge, so wondered about the mechanincs of this magic.#2019-12-2021:02borkdudeAh. Well, clj-kondo has special rules for analyzing several built-in vars/forms, it can't magically know otherwise#2019-12-2021:02borkdudeThere is no metadata or anything to go by#2019-12-2021:03borkdudeso if you encounter a name like clojure.core/let you know the first one is a binding vector#2019-12-2021:03pezCool. I thought as much, but good to know for sure.#2019-12-2021:03borkdudeMost of this code is in clj-kondo.impl.analyzer.clj#2019-12-2021:03pezThanks!#2019-12-2218:39geraldodev@borkdude Thanks a lot for clj-kondo. It is like a companion for me. It has made clojure fun again.#2019-12-2218:40borkdudeThanks for the compliment, much appreciated!#2019-12-2219:17borkdude@U0516053R Are you alright we me citing your line in the README?#2019-12-2219:39geraldodevsure!#2019-12-2418:55fmnoisehi everyone, sometimes I have the following issue
Suspicious state from syntax checker clj-kondo-clj: Flycheck checker clj-kondo-clj returned non-zero exit code 3, but its output contained no errors: <stdin>::: error: Insufficient input.
linting took 22ms, errors: 1, warnings: 0

Try installing a more recent version of clj-kondo-clj, and please open a bug report if the issue persists in the latest release.  Thanks!
#2019-12-2418:56fmnoiselatest clj-kondo installed#2019-12-2418:57borkdude@fmnoise Co-incidentally I just fixed a similar problem. Could you post your entire file or narrowed down file that still produces this error?#2019-12-2418:59borkdudeI think I know what's wrong#2019-12-2418:59borkdudebut I want to have a repro to ensure that this is it#2019-12-2419:01fmnoise@borkdude it's closed-source but I'll try to find minimal reproducible piece which causes that error and will back to you with results#2019-12-2419:02borkdudethanks#2019-12-2419:14fmnoise
(assoc {} :a 2 :(java.util.Date.))
#2019-12-2419:14fmnoisethis one causes issue#2019-12-2419:14borkdudeis the colon supposed to be in front of that expression?#2019-12-2419:15borkdudeand it seems you're missing one argument#2019-12-2419:15fmnoise(assoc {} :a 2 😛 (java.util.Date.))#2019-12-2419:15fmnoiseoh, slack 😞#2019-12-2419:16fmnoise
(assoc {} :key1 2 :key2 (java.util.Date.))
#2019-12-2419:16fmnoiseslack's eating :b for some reason#2019-12-2419:16borkdudeok, I can repro that, thanks#2019-12-2419:18borkdude@fmnoise Made an issue for it here: https://github.com/borkdude/clj-kondo/issues/677 I'll fix it soon#2019-12-2419:18fmnoisethanks @borkdude!#2019-12-2419:19borkdudefor now you can override your type config for clojure.core/assoc if you want#2019-12-2419:21fmnoiseI just replaced (java.util.Date) with our internal (now) helper, so that's fine, thanks 😄#2019-12-2419:23borkdudeok 🙂#2020-12-3021:35borkdudeMade a thing using clj-kondo to cut out the unused vars from a project: https://github.com/borkdude/carve#2020-12-3112:41jahson@borkdude Hi, Michel! I'm slowly trying to implement a clj-kondo based checker for re-frame events and subscriptions, but there's not enough information about arguments at the moment. After reading the code I think that I should extend analyzer.clj. Am I right?#2020-12-3112:43borkdudeanalyzer.clj is where most of the action happens yes#2020-12-3112:47jahsonThanks!#2020-01-0115:32Duck Nebuchadnezzarclj-kondo is failing to ignore the symbol in a devcards.core/deftest form, but cljs.test/deftest works fine and :lint-as {devcards.core/deftest cljs.test/deftest} doesn't seem to do it. Any ideas?#2020-01-0115:35borkdudeCan you provide a small reproducable snippet in the form:
$ clj-kondo --config '{:lint-as ...}' --lint - <<< '(ns foo (:require [devcards.core :as dc])) (dc/deftest ...))'
and show me what the current (undesired) behavior is?
#2020-01-0115:35Duck Nebuchadnezzarsure. one sec#2020-01-0115:41Duck Nebuchadnezzar
clj-kondo --config '{:lint-as {devcards.core/deftest cljs.core/deftest}}' --lint - <<< '(ns foo (:require [cljs.test :refer-macros [is]] [devcards.core :refer-macros [deftest]])) (deftest main-test (is (= 1 1)))'
#2020-01-0115:42Duck NebuchadnezzarI want the error about main-test silenced#2020-01-0115:44borkdudethat's weird yes, I have a similar situation with spartan.test which I tested yesterday and worked fine: https://github.com/borkdude/spartan.spec/blob/master/.clj-kondo/config.edn I'll look into it#2020-01-0115:45Duck Nebuchadnezzardefcard-rg fails too, but I figured if I could solve one, I could solve the other#2020-01-0115:45borkdudeyeah, it's weird. give me a moment to figure it out#2020-01-0115:48borkdudehmm, this works:
clj-kondo --config '{:lint-as {spartan.test/deftest clojure.test/deftest}}' --lint - <<< '(ns foo (:require [spartan.test :refer [deftest]])) (deftest main-test)'
#2020-01-0115:49borkdudethis also works:
clj-kondo --config '{:lint-as {devcards/deftest clojure.test/deftest}}' --lint - <<< '(ns foo (:require [devcards :refer [deftest]])) (deftest main-test)'
#2020-01-0115:49borkdudethis also works:
clj-kondo --config '{:lint-as {devcards.core/deftest clojure.test/deftest}}' --lint - <<< '(ns foo (:require [devcards.core :refer [deftest]])) (deftest main-test)'
#2020-01-0115:50borkdudeaaand this also works:
clj-kondo --config '{:lint-as {devcards.core/deftest cljs.test/deftest}}' --lint - <<< '(ns foo (:require [devcards.core :refer-macros [deftest]])) (deftest main-test)'
#2020-01-0115:50borkdudeand this also works:
clj-kondo --config '{:lint-as {devcards.core/deftest cljs.test/deftest}}' --lint - <<< '(ns foo (:require [cljs.test :refer-macros [is]] [devcards.core :refer-macros [deftest]])) (deftest main-test (is true))'
^ @duck
#2020-01-0115:51borkdudeNot sure what the difference is, maybe a weird typo somewhere?#2020-01-0115:51Duck Nebuchadnezzarthat one does indeed pass for me#2020-01-0115:53borkdudeah, cljs.core instead of cljs.test#2020-01-0115:55borkdude@duck Were you the same person asking me about orchestra/defn-spec? I'm thinking about a solution like this: https://github.com/borkdude/clj-kondo/issues/682#2020-01-0115:55Duck NebuchadnezzarThe only difference is forms inside is#2020-01-0115:56borkdudeThe difference is cljs.core instead of cljs.test#2020-01-0115:56borkdudeThere is no cljs.core/deftest#2020-01-0120:53borkdude^ @duck#2020-01-0120:53borkdude(not sure if you read this)#2020-01-0115:55Duck NebuchadnezzarThat was me#2020-01-0311:53robert-stuttafordis it possible to make clj-kondo ignore (comment) forms entirely?#2020-01-0311:54borkdude@robert-stuttaford what are things that you would like to have ignored from comment forms? I usually want comment forms (= example code) to be free of errors as well#2020-01-0311:55robert-stuttafordif i can switch off through configuration, then i can produce a report of all linting errors in production code. means it's possible to have 100% clean CI report and not be concerned with developer-time comments at all#2020-01-0311:55robert-stuttafordi also like it on for comments, i use it that way a lot!#2020-01-0311:56robert-stuttafordif i can have that, and figure out a way to lint rum components (i want this enough to contribute it), then we basically have a perfect workflow here!#2020-01-0311:57borkdudecan you try :skip-comments true?#2020-01-0311:58robert-stuttafordthat did something; i got less output than before. digging deeper...#2020-01-0311:59robert-stuttafordyeah that seems to be working great!#2020-01-0312:00borkdudeI kinda forgot about that config.. nice that it's still working 🙂#2020-01-0312:00robert-stuttafordhttps://github.com/borkdude/clj-kondo/pull/684 🙂#2020-01-0312:01robert-stuttafordthank you sir. also, carve is -ing fantaaaaaastic 👏#2020-01-0312:01borkdude@robert-stuttaford For rum, maybe this could work: https://github.com/borkdude/clj-kondo/issues/682#2020-01-0312:02borkdudeso then you can do {:lint-as {rum/def-foo clj-kondo.lint-as-macros/defn-1}}#2020-01-0312:02borkdudethat would work for a lot of weird def macros#2020-01-0312:03robert-stuttafordit's certainly worth a try! i'd be totally ok with clj-kondo ignoring the rum mixins and just providing the usual linting for the args and body. the issue of course is instructing clj-kondo where the args can be found, and where the body starts!#2020-01-0312:04borkdudethe idea of that issue is to completely ignore the bindings, just registering the fact that is defines a var, so you won't get an unresolved symbol warning#2020-01-0312:04borkdudethat seems to cover the most weird def-macros that aren't natively supported yet#2020-01-0312:04robert-stuttafordright#2020-01-0313:31mhjortHas someone already find out what is required clj-kondo configuration for making compojure-api work with clj-kondo? Macros like this cause issues: https://github.com/metosin/compojure-api/blob/master/src/compojure/api/core.clj#L60#2020-01-0313:32mhjortThese macros are used like this (POST "/" request (handle-certificate-request request)). clj-kondo will then generate following error: error: unresolved symbol request#2020-01-0313:33borkdude@mhjort there is built-in support for compojure.core; maybe you can use :lint-as?#2020-01-0313:33borkdudesee https://github.com/borkdude/clj-kondo/releases/tag/v2019.11.07#2020-01-0313:44mhjortThanks! I used same kind of :lint-asand :exclude for compojure-api macros. That helped#2020-01-0313:45juhoteperiCompojure support works for basic cases but won't support Compojure-api restructure binding forms like (GET "/:id" req :path-params [id :- s/Str] ...)#2020-01-0313:46borkdudein that case might just want to use :excludeyes#2020-01-0313:46juhoteperiReitit code will be easier to lint as it is just data 🙂#2020-01-0314:23robert-stuttafordwhy does it say redundant form for #(do (prn %) (something %)) ? pointing at #( . i guess it's because #(do ...) becomes (fn [] (do ...)) ...#2020-01-0315:38dominicmFwiw, I would consider that bad style.#2020-01-0809:05robert-stuttafordfair 🙂#2020-01-0314:24borkdude@robert-stuttaford that's probably joker? may I refer you to #joker for that?
$ clj-kondo --lint - <<<  '#(do (prn %) (something %))'
<stdin>:1:15: error: unresolved symbol something
linting took 42ms, errors: 1, warnings: 0
$ /usr/local/bin/joker --lint - <<<  '#(do (prn %) (something %))'
<stdin>:1:15: Parse error: Unable to resolve symbol: something
<stdin>:1:2: Parse warning: redundant do form
#2020-01-0314:25robert-stuttafordapologies, hard to tell where it's coming from!#2020-01-0314:25robert-stuttafordyou must get that a lot heh#2020-01-0314:25borkdudenot really, mostly from you 😉#2020-01-0314:26robert-stuttaford😊#2020-01-0314:27borkdudeno worries, I was only kidding, just to be clear 😉#2020-01-0314:27robert-stuttafordhaha i'm not fazed. having a blast linting me codes#2020-01-0410:39lispycloudsIf I use a fully qualified ns like ( stream) clj-kondo warns with Unresolved namespace . Are you missing a require? but its fine with (clojure.string/split ...). Is this problem?#2020-01-0410:43borkdudeYou are always supposed to add a require even if it works, since you should not rely on a namespace already being loaded elsewhere#2020-01-0410:46lispycloudsbut arent namespaces like and clojure.string are loaded by default?#2020-01-0410:47borkdudeno#2020-01-0410:47borkdudewell clojure.string is, but you should not rely on it#2020-01-0410:47borkdudee.g. if clojure.spec loads clojure.string, you're lucky, but if spec doesn't you're not. it's an implementation detail#2020-01-0410:48lispycloudsi mean i can do a () in a plain REPL without requiring, it still means something else has loaded it?#2020-01-0410:50borkdudeyeah, maybe your REPL tooling or Clojure main has, but that doesn't mean it will still have been loaded in a compiled artifact for example#2020-01-0410:51borkdudeAccording to Alex Miller you should not rely on it. I take his word for it.#2020-01-0410:51lispycloudsah, good to know. thanks! 😄#2020-01-0410:52lispycloudsshouldn't it warn for clojure.string too? just to be consistent? this diff is what bothered me in the first place#2020-01-0410:52borkdudekondo you mean? doesn't it?#2020-01-0410:52lispycloudsno#2020-01-0410:53borkdude#2020-01-0410:53lispycloudsokay somethings up with my editor then :thinking_face:#2020-01-0410:54borkdudetry flycheck-verify-setup#2020-01-0410:56lispyclouds#2020-01-0410:57borkdudecan you past the full namespace?#2020-01-0410:58lispycloudsah now i see it#2020-01-0410:58lispycloudslong back there is a require picard-facepalm#2020-01-0410:59borkdude🙂#2020-01-0410:59lispycloudsthanks anyways 🙂#2020-01-0510:09yuhanCan clj-kondo infer argument/return types of a function from type hints?#2020-01-0510:10yuhani.e. I can see it currently doesn't, but would that be within its capabilities / design scope?#2020-01-0510:15yuhanI recently made a typo with a clojure.string function, looked at clj-kondo's types.clojure.string namespace to see that it hadn't been specced yet, then saw from the clojure.string source that most functions were already hinted with ^String or ^CharSequence#2020-01-0510:16borkdudeThis currently works:
(defn foo ^String [])
(inc (foo))
#2020-01-0510:16borkdudeyou'll get a warning about string instead of number#2020-01-0510:18yuhanhmm, but (inc (string/reverse "abc")) doesn't give a warning#2020-01-0510:18yuhan
(defn ^String reverse
  "Returns s with its characters reversed."
  {:added "1.2"}
  [^CharSequence s]
  (.toString (.reverse (StringBuilder. s))))
#2020-01-0510:19yuhanhuh, so there are two different places where the return type hint can go#2020-01-0510:20borkdudethat's because the var is hinted, not the return type#2020-01-0510:20borkdudewhich is wrong#2020-01-0510:20borkdudeI think#2020-01-0510:26yuhanYeah, apparently the compiler detects that as a valid type hint 😮#2020-01-0510:27yuhan
(set! *warn-on-reflection* true)
(defn f1 [])
(defn f2 ^String [])
(defn ^String f3 [])

(fn []
  (.length (f1))
  (.length (f2))
  (.length (f3)))
^ Only f1 gets a reflection warning
#2020-01-0510:28yuhanEven though it's not documented on https://clojure.org/reference/java_interop#typehints#2020-01-0510:28borkdudeso the type hint on a var also gets used for inferring the return type? if you can confirm that this is correct behavior clj-kondo could adopt this#2020-01-0510:30borkdudeby checking this in #clojure with e.g. Alex Miller#2020-01-0510:45yuhanI posted it on https://ask.clojure.org/index.php/8993/where-to-place-function-return-type-hints#2020-01-0712:34yuhanLooks like the answer is yes, tags on function vars can be used to infer the return type#2020-01-0712:35yuhanAlthough the arglist tag takes precedence#2020-01-0712:37borkdudeIssue welcome. After that, PR + tests also welcome.#2020-01-0712:38borkdudeNote that you have to re-run script/extract-var-info after making the change, so the tags will be picked up from the code.#2020-01-0514:04Kari MarttilaIs there a functionality in clj-kondo IntelliJ IDEA integration to have all warnings and errors listed in IDEA's "Errors box" and then double click certain error/warning and cursor would go to that row in source file?#2020-01-0520:07borkdudeI don't know IntelliJ well enough to answer this.#2020-01-0514:04Kari MarttilaI really like clj-kondo, good tool!#2020-01-0520:07borkdudeThanks!#2020-01-0615:20Björn EbbinghausI get Unresolved namespace warning with a location that doesn't make sense. The code where the warning is boilerplate and has nothing to do the missing requirement it warns me about. line and column are pointing to whitespace. Even if I require the namespace I still get the warning. Details about the warning and it's location. ./src/main/decide/server_components/config.clj:17:27: warning: Unresolved namespace decide.server-components.ldap. Are you missing a require? https://github.com/hhucn/decide/blob/master/src/main/decide/server_components/config.clj#L17:27#2020-01-0615:23borkdude@mroerni I've pasted that file in a local file here and I don't get this warning. Maybe something is up with your editor?#2020-01-0615:24borkdudeThis is the output I'm getting:
$ clj-kondo --lint foobar.clj
foobar.clj:20:11: error: unresolved symbol config
linting took 13ms, errors: 1, warnings: 0
Maybe you can try the same.
#2020-01-0615:25Björn EbbinghausHmm... Only clj-kondo --lint . has the warning. 😕#2020-01-0615:25borkdudeAh, only if you lint the entire dir?#2020-01-0615:26Björn Ebbinghausyes#2020-01-0615:26borkdudeI'll try the repo#2020-01-0615:27Björn Ebbinghausclj-kondo --lint src -> Warning clj-kondo --lint src/main -> No warning#2020-01-0615:30borkdudeit's coming from your user file#2020-01-0615:31borkdude#2020-01-0615:31borkdudeI'm not sure why the filename is wrong there#2020-01-0615:32borkdudethat's definitely a bug. a small repro of this + an issue would be nice#2020-01-0714:16Björn EbbinghausDone. Don't know how to make a better repro than the commit in the repo, since the problem is not reproducible in a single file. https://github.com/borkdude/clj-kondo/issues/691#2020-01-0714:19borkdudeok, thanks!#2020-01-0621:32thumbnailhi 👋:skin-tone-2: first off thanks for clj-kondo :thumbsup::skin-tone-2: Really solid stuff. I noticed clojure.core/bound-fn was giving me unresolved symbol errors. By adding :lint-as {clojure.core/bound-fn clojure.core/fn} to the config this was resolved though.#2020-01-0621:33borkdudeThanks. Feel free to post an issue about this.#2020-01-0621:33thumbnailShould I PR to append that config here; https://github.com/borkdude/clj-kondo/blob/6584375693a63e230804af9787149add6fdfff0d/src/clj_kondo/impl/config.clj#L76 or should I just create an issue?#2020-01-0621:34borkdudeCreate an issue with the problem and the workaround. I'd first like to see why bound-fn wasn't recognized in clj-kondo and inspect the root error#2020-01-0621:34thumbnailFigured as much. will do#2020-01-0621:36borkdudeAh I see. clj-kondo recognizes that symbol, but doesn't lint it correctly. The config makes sense, but should probably be built into analyzer.clj. PR for that is welcome.#2020-01-0621:37borkdudeThe place where it should be added is analyze-call#2020-01-0621:45thumbnailI’ll create the issue and look into a PR soon 🙂 Thanks for the pointer#2020-01-0621:54borkdudethank you too! I saw on Github that you live in Overijssel, that's where I come from too (but I don't live there anymore)#2020-01-0622:04thumbnailIt’s such a small country :flag-nl:#2020-01-0622:07borkdudecheck out #clojure-nl as well#2020-01-0622:32thumbnailI’m actually already in that group 😅 just pretty passive usually.#2020-01-0809:59dharriganThere's quite a common macro called when-let*, as described here: #2020-01-0809:59dharriganPresently, I get an error from clj-kondo on linting#2020-01-0810:00dharriganSo I'm trying to get clj-kondo to do the right thing#2020-01-0810:00dharrigani.e., {:lint-as {foo.bar/when-let* clojure.core/let}}#2020-01-0810:00dharriganthat doesn't seem to work (still reports an error that the symbol cannot be resolved)#2020-01-0810:02dharriganif I change it to clojure.core/when-let then it complains thus error: when-let binding vector requires exactly 2 forms#2020-01-0810:02dharriganAny suggestions on how to get clj-kondo to do the right thing?#2020-01-0810:12yuhan@dharrigan I have the same macro in my util ns and it's linted as clojure.core/let with no issues#2020-01-0810:12yuhanmaybe check for typos?#2020-01-0810:13dharriganthanks - will check#2020-01-0810:14dharriganAh - yes, I forgot - I had joker as well#2020-01-0810:14dharrigani.e., let g:ale_linters = {'clojure': ['clj-kondo', 'joker']}#2020-01-0810:14dharriganremoving joker worked#2020-01-0822:41practicalli-johnI removed joker last year. It's a much better experience with just clj-kondo#2020-01-0810:14dharriganconfirmation that it worked for you, made me look elsewhere 🙂#2020-01-0810:17yuhanI'm pretty sure clj-kondo's features are a superset of joker's by now, there's little reason to have both#2020-01-0810:19dharriganYeah, I've removed it 🙂#2020-01-0816:35borkdudeI think you can use {:clj-kondo/config {:linters ...}} as namespace metadata. Doesn't work for all linters, but I believe it works for :unresolved-symbol#2020-01-0816:35borkdudeoh I responded while not having read your code... sorry 🙂 I see you're already doing that#2020-01-0816:36borkdudeyou need to quote the metadata value: so '{:linters ...}#2020-01-0816:36borkdude^ @deleted-user#2020-01-0816:51deletedit worked!#2020-01-0816:54borkdudeBtw, I haven't got testing yet in spartan.test, but that would be nice. Lint-as should also work here: {:lint-as {spartan.test/deftest clojure.test/deftest}}#2020-01-0816:55borkdudeI'm going to add testing right away.#2020-01-0817:03borkdudeAdded#2020-01-0817:27borkdudeI'll add thrown? and thrown-with-msg? later today#2020-01-0910:29yuhanwould it be possible for clj-kondo to lint function arguments? eg. (update m k f x) would be an error if f did not take 2 args or x was the wrong type#2020-01-0910:37borkdudeWorth a research project. I guess it could be made to work#2020-01-0918:24mynomotoI need to use a private var on a library, can clj-kondo ignore the error only for a specific var?#2020-01-0918:36borkdudeno, but if you use #'private/var that works?#2020-01-0918:54mynomotoIt's on clojurescript so it just works.#2020-01-0918:54mynomotoI'm trying to configure the namespace to ignore the private var linter#2020-01-0918:55borkdudeMaybe you can do it in the namespace metadata? Not sure if it works for that specific linter#2020-01-0918:55borkdude(ns foo "foo docs" {:clj-kondo/config '{:linters {...}}})#2020-01-0918:59mynomotoI thought that :private-call could be the one but doesn't seems to work.#2020-01-0919:00mynomotoCan I exclude a single namespace from linting?#2020-01-0919:01borkdudethis seems to work:
(ns foo "foo docs"
    {:clj-kondo/config '{:linters {:private-call {:level :off}}}})

(clojure.core/is-annotation? 1)
#2020-01-0919:02borkdudethe linter should actually be renamed to :private-var since it should also report usages of private vars. I'll make an issue for that#2020-01-0919:02borkdude(I'll make sure it will be non-breaking)#2020-01-0919:03mynomotoDo I have to use the docstring? I tried without it and it didn't work. Not sure if it makes a difference but the variable I'm using is created by defprotocol.#2020-01-0919:04mynomotoActually is a deftype.#2020-01-0919:05borkdudeno, the docstring is optional.#2020-01-0919:06borkdudeThis works:
(ns bar)

(deftype ^:private Foo [])

(ns foo
  {:clj-kondo/config '{:linters {:private-call {:level :off}}}}
  (:require [bar]))

(clojure.core/is-annotation? 1)
(bar/Foo)
#2020-01-0919:06mynomotoLooks like quoting is mandatory?#2020-01-0919:06borkdudeyes, Clojure will evaluate your metadata so you have to quote them#2020-01-0919:07mynomotoI just added the ' and it worked.#2020-01-0919:07borkdude🎉#2020-01-0919:08mynomotoBut there is no symbols on it. I cannot see why quoting is necessary in this case.#2020-01-0919:08mynomotoThanks!#2020-01-0919:09borkdudeBecause symbols are evaluated by Clojure#2020-01-0919:09borkdudeoh I see#2020-01-0919:09borkdudehmm, yeah, that's weird 🙂#2020-01-0919:10borkdudeclj-kondo just always expects a quoted value there because most of the time there are symbols in there#2020-01-0919:10borkdudeit's hard-coded in the linter#2020-01-0919:12mynomotoOk, that makes sense. Thanks for the explanation.#2020-01-0920:58mikerodAnyone faced getting clj-kondo linter error: unresolved symbol for symbols used in a clj comment macro?#2020-01-0920:58mikerodI tried both :exclude on (comment) and (clojure.core/comment), but doesn’t seem to fix it#2020-01-0921:01mikerodusing latest ver [clj-kondo "2019.12.14"]#2020-01-0921:01borkdude@mikerod By default clj-kondo will lint comments as if it's "real" code, because often that's useful during experimentation. But you can turn it off using :skip-comments true#2020-01-0921:01borkdudehttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md#ignore-the-contents-of-comment-forms#2020-01-0921:02mikerodoh interesting. I was on that doc page, but didn’t expect it to be a separate option like that#2020-01-0921:02mikerodthat makes sense, I guess the case I had was somewhat special then. perhaps it should be turned into something more valid to avoid needing this skip.#2020-01-0921:05borkdudethat option is often useful for CI as well#2020-01-0921:06mikerodwhy CI?#2020-01-0921:07borkdudebecause you don't want to trigger any false alarms in CI?#2020-01-0921:11mikerodI see#2020-01-0921:11mikerodwas thinking there was something special about comment in CI#2020-01-0921:11mikerodI see what you’re saying now though#2020-01-1009:53borkdudewho was asking me recently about orchestra/defn-spec? I forgot, but I now have a solution for it on master. possibly also for rum macros (cc @robert-stuttaford)
{:lint-as {foo/my-defn clj-kondo.lint-as/def-catch-call}}
#2020-01-1009:54borkdudeAh, it was probably@duck#2020-01-1010:14borkdudehttps://github.com/borkdude/clj-kondo/releases/tag/v2020.01.10#2020-01-1013:13littlelino windows build this time?#2020-01-1013:25borkdudeFixed. thanks#2020-01-1013:33littleliI'll do the bump later today in scoop#2020-01-1015:38littlelidone 🎉#2020-01-1015:41borkdudeThanks!#2020-01-1011:09robert-stuttafordthanks @borkdude - the catch-all is definitely feeling better!#2020-01-1011:11borkdude@robert-stuttaford Feel free to provide examples of code in the rum issue. That's what's still missing. Without any repros I can't do much#2020-01-1011:11borkdudeBut if the catch-all is sufficient, that'll do for now#2020-01-1011:19robert-stuttafordi'll write a short summary of the concern so it's there for future improvements#2020-01-1011:25robert-stuttafordi did so, @borkdude https://github.com/borkdude/clj-kondo/issues/536#issuecomment-572997925 - super happy to update this comment if better information comes from elsewhere 🙂#2020-01-1011:41borkdudeResponded in the issue.#2020-01-1012:13Lauri LehmijokiHello, I have the following function:
(defn wrap-internal-error [_handler]
  (fn [_req]
    (try+
     (_handler _req)
     (catch [:type :too-large-pdf] {:keys [request]}
     ...  
and running clj-kondo gives me the following error: my_file.clj:22:44: error: unresolved symbol request. The try+macro is from slingshot:0.12.2. Any suggestions on how to fix or work around the error?
#2020-01-1012:15borkdude@lauri.lehmijoki You can ignore unresolved-symbols using a configuration: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-unresolved-symbols-from-being-reported so something like:
{:linters {:unresolved-symbol {:exclude [(foo/try+)]}}}
#2020-01-1012:17Lauri Lehmijokithank you so much!#2020-01-1013:33Lauri LehmijokiI have the following expression:
(context "/api" []
                       :header-params [{authorization :- (describe s/Str (str "API key. For demo use: [TOKEN " @api-key "]")) nil}]
and running clj-kondo gives me the following error: my_file.clj:117:41: error: unresolved symbol authorization. The context macro is from https://github.com/metosin/compojure-api/blob/85738b802c7f150f4f550ffca91a4782c75f8091/src/compojure/api/core.clj#L58. Any suggestions on how to fix this one?
#2020-01-1013:33Lauri LehmijokiMy .clj-kondo/config.ednis as follows:
{:linters {:unresolved-symbol {:exclude [(compojure.api.core/context)]}}
 :output {:progress true}}
#2020-01-1013:39borkdudeThis works for me:
(ns foo
  {:clj-kondo/config '{:linters {:unresolved-symbol {:exclude [(compojure.api.core/context)]}}}}
  (:require [compojure.api.core :refer [context]]))


(context "/api" []
         :header-params
         [{authorization :- (describe s/Str (str "API key. For demo use: [TOKEN " @api-key "]")) nil}])
#2020-01-1013:42borkdudeI mean, no errors in that file#2020-01-1013:43Lauri LehmijokiThanks, I realised that my namespace actually required compojure.api.sweet/context instead of compojure.api.core/context. With config.edn being
{:linters {:unresolved-symbol {:exclude [(compojure.api.sweet/context)]}}
                           :output {:progress true}}
I see no clj-kondo errors. Thank you for clj-kondo and fast responses here on Slack!
#2020-01-1013:39Filipe Silva@borkdude I'm starting to think that using https://github.com/borkdude/clj-kondo/pull/696 is better than having a npm package for shadow-cljs projects#2020-01-1013:40Filipe Silvathoughts?#2020-01-1013:41borkdudeif you want to invoke clj-kondo on the JVM, you can just use it as a dependency. if you want to run the binary, then a package manager like npm or scoop may be better#2020-01-1013:45Filipe Silvayeah in the shadow case there is a JVM available#2020-01-1013:45Filipe Silvatbh it wasn't clear (to me) at all how to do it with shadow in the same way it was possible to do it with tools.deps and lein#2020-01-1013:45Filipe Silvahence adding the pr#2020-01-1013:46borkdudeok#2020-01-1014:28Filipe Silvadoes the :exclude-files config entry support wildcards/globs/something to group things by, or does it need each individual file to be listed?#2020-01-1014:30borkdudeI had to look it up, but it seems each string in that entry is interpreted as a Java regex: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#include-and-exclude-files-from-the-output#2020-01-1014:31borkdudeon which re-find is called#2020-01-1014:31Filipe SilvaI've been trying to exclude a folder for the last 10 minutes and haven't had much success....#2020-01-1014:32borkdudewhat's the folder name and what did you try?#2020-01-1014:32Filipe SilvaI'm running shadow-cljs run clj-kondo.main --lint src/#2020-01-1014:32Filipe SilvaI want to exclude everything in src/cljs/devcards/#2020-01-1014:33borkdudeyou probably need to write: "src//cljs//devcards//"#2020-01-1014:34Filipe Silvawhat's the double slash?#2020-01-1014:34borkdudeNope, this should just work:
user=> (re-find (re-pattern "/src/cljs/devcards") "/src/cljs/devcards/foo.cljs")
"/src/cljs/devcards"
#2020-01-1014:35borkdudeso only: "/src/cljs/devcards"#2020-01-1014:35borkdudebut if the paths are reported relatively, you need to omit the starting slash maybe#2020-01-1014:36Filipe SilvaI get reports like this#2020-01-1014:36Filipe Silva
src\cljs\devcards\d_reactive.cljs:87:16: warning: unused binding *x
src\cljs\devcards\d_reactive.cljs:87:25: error: unresolved symbol conn
src\cljs\devcards\d_reactive.cljs:88:16: warning: unused binding *p
src\cljs\devcards\d_reactive.cljs:90:16: warning: unused binding *titles
src\cljs\devcards\d_reactive.cljs:109:27: error: unresolved symbol _
src\cljs\devcards\d_reactive.cljs:135:24: error: unresolved symbol dispatch
src\cljs\devcards\d_reactive.cljs:141:22: error: unresolved symbol ctx
src\cljs\devcards\keys.cljs:11:23: error: unresolved symbol x
src\cljs\devcards\keys.cljs:25:25: error: unresolved symbol app-state
src\cljs\devcards\keys.cljs:37:23: error: unresolved symbol ctx
src\cljs\devcards\keys.cljs:58:24: error: unresolved symbol id
#2020-01-1014:36Filipe Silvamaybe it's because I'm on windows#2020-01-1014:36Filipe Silvaso the slash never works?#2020-01-1014:37Filipe SilvaIf I just use :output {:exclude-files ["d_reactive.cljs"]} I can do away with the first file#2020-01-1014:37Filipe Silvabut so far I'm unable to exclude the folder...#2020-01-1014:38borkdude
user=> (re-find (re-pattern "src\\\\cljs\\\\devcards\\\\")  "src\\cljs\\devcards\\keys.cljs")
"src\\cljs\\devcards\\"
#2020-01-1014:39borkdudeso the pattern is what goes into re-pattern#2020-01-1014:39Filipe Silvaok I can't do that then, because now the pattern might work locally but it will never work on CI or colleagues machines.... 😕
#2020-01-1014:39Filipe Silvais there a way to exclude namespaces?#2020-01-1014:39Filipe Silvathose wouldn't have path slash problems#2020-01-1014:40borkdudeno. I think in this case you just want to pass multiple paths:
--lint src\cljs\your-code src\cljs\your-other-code
#2020-01-1014:41borkdudethe same paths that you have in your production build basically#2020-01-1014:42Filipe Silvaok I'll try that#2020-01-1014:42Filipe Silvathank you#2020-01-1015:53borkdudethese are just patterns passed to re-pattern and then applied to the paths with re-find. so there's nothing OS or filesystem specific in there#2020-01-1015:56borkdudeyou can just put more patterns in there to also support Windows#2020-01-1015:56borkdudeor indeed, use a more flexible regex#2020-01-1016:05Filipe Silvathat can be done, but it's one of those "surprising in a bad way" things#2020-01-1016:05Filipe Silvathe double escapes were very surprising#2020-01-1016:05borkdudenot if you know clojure#2020-01-1016:05borkdude😉#2020-01-1016:06Filipe SilvaI don't think it's a matter of knowing the language, double escapes exist outside of clojure too#2020-01-1016:06borkdudebut I agree it is annoying. on the other hand, I don't know anyone who uses this feature#2020-01-1016:07Filipe SilvaI wouldn't say it's a very important thing, no#2020-01-1016:07Filipe Silvait's just one of those "oh yeah I'm on windows so everything is harder" kind of thing#2020-01-1016:08Filipe Silvatbh most of the windows compat problems in the platforms I've come across are just path separator issues hahah#2020-01-1016:08borkdudeyep#2020-01-1016:09borkdudeit took some effort to make the tests work on Windows, mostly due to that#2020-01-1016:10Filipe Silvaon another project we tried to put a path abstraction on top of both unix and windows paths and then... we ended up with 3 types of paths to make work 😐#2020-01-1016:10borkdudelol#2020-01-1015:23Filipe Silvaanother question please#2020-01-1015:24Filipe Silvais there any good way of knowing the name of the rule that's failing?#2020-01-1015:24Filipe SilvaI'm going through a codebase and need to add some exceptions#2020-01-1015:24Filipe Silvasome are straightforward enough to guess like unresolved-symbol#2020-01-1015:24borkdudeyou can figure it out using the EDN or JSON output#2020-01-1015:24Filipe Silvagotcha#2020-01-1015:24borkdudeor look at clj-kondo/impl/config.clj#2020-01-1015:25Filipe SilvaI was looking at that file but some stuff is hard to match#2020-01-1015:25Filipe Silvahttps://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/config.clj#2020-01-1015:25Filipe Silvalike use the idiom (seq x) rather than (not (empty? x))#2020-01-1015:26borkdudehttps://github.com/borkdude/clj-kondo/blob/e8a5deed6df302bdd56406e78b3fdc94614682c6/src/clj_kondo/impl/config.clj#L54#2020-01-1015:27Filipe Silvahah#2020-01-1015:28Filipe SilvaI was looking for prefer use seq idiom#2020-01-1015:29borkdudeIf you have any ideas about how to make this more accessible, e.g. by relating messages and their key in a table or something, PR welcome 🙂#2020-01-1015:29Filipe SilvaI know tslint shows the rule name somewhere#2020-01-1015:30borkdudemaybe that could also be a configuration option... badum-tss#2020-01-1015:30Filipe Silvabut with tslint the usual pattern is to add an exclude comment so it is slightly different#2020-01-1015:30Filipe SilvaI don't know if clj-kondo allows exclude comments too#2020-01-1015:31borkdudenot at the moment. I'm holding back on that a bit, since I don't want to confront users with all kinds of tooling metadata#2020-01-1015:31Filipe SilvaI'll open an issue for showing the rule name somewhere for this scenario#2020-01-1015:31borkdudeok#2020-01-1016:10Filipe Silvaif I have a macro that I can't/know how to make work with :lint-as, is there a good way of just ignoring stuff using it?#2020-01-1016:11Filipe Silvae.g. clojure.core.match#2020-01-1016:11Filipe SilvaI can destructure inside of it#2020-01-1016:11Filipe Silva
(match [action]
                                            [{:test   t
                                              :action a}] (when (t evt)
                                                            (a evt))
                                            [action]      (do
                                                            (.preventDefault evt)
                                                            (action evt))))
#2020-01-1016:12Filipe Silvabut will get unresolved symbol t errors#2020-01-1016:12borkdude1) There is an issue to add support for core.match. 2) You can ignore unresolved symbols inside a call, see config docs#2020-01-1016:14Filipe Silvahttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-unresolved-symbols-from-being-reported#2020-01-1016:14Filipe SilvaI see now#2020-01-1016:14Filipe Silvathank you#2020-01-1017:24aisamu(This might be unrelated to clj-kondo itself, but I couldn't find a #nix channel or something like that 🙂 - feel free to remove this!) Would it be feasible to make a clj-kondo's nix package that also works on Macs? I got the dreaded clj-kondo/default.nix:45 is not supported on ‘x86_64-darwin’ while trying to add it to a project. Some googling made me realise that my current nix-fu is not even close to sufficient to be able to diagnose/fix this 😬#2020-01-1017:25aisamu(@UKFSJSM38 tagging you because I can see you got a PR accepted on that file!)#2020-01-1017:35ericdallo@aisamu clj-kondo depends on graalvm(https://github.com/NixOS/nixpkgs/pull/75733/files#diff-fdcc5997b875e2e3f53ef279f9e38864R48) that graalvm on nix its only supported to x86_64-linux users(https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/compilers/graalvm/default.nix#L407) :/#2020-01-1017:38ericdalloI don't know for sure if this is the real problem, but its what looks like#2020-01-1018:34joseHi, I made the first version of the nix package. The problem is that graalvm doesn't build currently on Darwin (for nixos). I think there is a PR to fix that, once graalvm works on Darwin you should be able to build clj-kondo on Darwin without any modifications#2020-01-1018:39joseBtw, for nix related questions, there is a relatively active community here: https://discourse.nixos.org/#2020-01-1017:24borkdude@aisamu It would probably best to talk to the package maintainers#2020-01-1017:26aisamuYup, but I'm unsure where nix package maintainers hang out 🙈. I know that at least one of them is here, so I thought it'd be worth a shot. Sorry for the noise!#2020-01-1017:27aisamu(and thanks a lot for clj-kondo, btw!)#2020-01-1017:28borkdude@aisamu This issue was originally created for the nixOS package: https://github.com/borkdude/clj-kondo/issues/414 you can ping the author of that issue there as well#2020-01-1017:29aisamuAh, that's indeed helpful!#2020-01-1017:50Filipe Silvais it possible to exclude unresolved namespaces?#2020-01-1017:50Filipe Silvaadding an exclude to the linter config doesn't seem to do it#2020-01-1017:50Filipe Silvahttps://github.com/borkdude/clj-kondo/blob/172d3fa53b39b7ed7dbe35f001debaafe5d0322b/src/clj_kondo/impl/namespace.clj#L201-L204 sounds like it should work with unresolved-symbol excludes instead#2020-01-1017:51Filipe Silvabut I'm not having luck adding the ns itself to the unresolved-symbol list#2020-01-1017:52Filipe SilvaI can, however, add the macro that uses the unresolved-namespace to the unresolved-symbol exclude list though#2020-01-1018:43borkdudewhich macro is that? can you give an example?#2020-01-1019:14Filipe Silvait's a the same as lazy-component in https://code.thheller.com/blog/shadow-cljs/2019/03/03/code-splitting-clojurescript.html#2020-01-1019:14Filipe Silvait's meant to take a namespace#2020-01-1019:17borkdudeyeah, clj-kondo assumes you forgot a require there, which is in most cases helpful, but maybe in a macro like this isn't. it looks at the exclusions in :unresolved-symbol though, as I suspected most macros that had this problem already needed such a rule there and it would be annoying to repeat rules for the same macro in two places#2020-01-1019:19borkdudeanother option is to just turn off that linting rule, or maybe it works for namespace local config, but I haven't tested that#2020-01-1205:21Duck NebuchadnezzarIs there any way to get clj-kondo to complain about problems like this? clj-kondo --lint - <<< '(ns foo) ::bar/baz'#2020-01-1208:31borkdude@duck You mean like, the namespace alias doesn't exist?#2020-01-1208:31borkdudeThat could probably be added under :unresolved-namespace, but isn't there right now#2020-01-1208:33borkdudeMade an issue for it#2020-01-1316:35mikerodHow can kondo be made to understand macros that define new symbols/vars?#2020-01-1316:38bfabryhttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md "lint a custom macro like a built in macro"#2020-01-1316:39bfabry"def" would be a macro that creates and binds new vars. "let" would be a macro that binds symbols#2020-01-1316:48borkdude@mikerod Any macro in particular?#2020-01-1316:57mikerod@borkdude no, custom macros#2020-01-1316:57mikerod@bfabry I don’t know that I see how that can work for that symbol then being recognized as available#2020-01-1316:57mikerodit can be worse too though really#2020-01-1316:58mikerod(def-my-thing Foo) could define a var like AutoFoo#2020-01-1316:58borkdude@mikerod what does the macro usage look like#2020-01-1316:58mikerodwhich is somewhat similar to perhaps the way a defrecord Foo makes fn’s map->Foo & ->Foo#2020-01-1316:59mikerodmacro usage is like above#2020-01-1316:59mikerod
(def-auto-gen foo)

;; later
(auto-foo :hi)
#2020-01-1316:59borkdudesearch for hugsql in the docs, there's a way how you can fix this with declare#2020-01-1316:59mikerodyeah, I see the declare option#2020-01-1317:00mikerodthat’s ok, I suppose. would be a lot to write#2020-01-1317:00borkdudeyou can also use a local namespace config which excludes those symbols from being reported, but that would be almost the same amount of work as the declare#2020-01-1317:00mikerodBasically I have huge list of def-thing that makes a wrapper type#2020-01-1317:00borkdudeor you can just turn the linter off in that namespace#2020-01-1317:00mikerodit also defines a “raw” type under an auto gen name#2020-01-1317:00mikerodand there’s just a lot of them#2020-01-1317:00mikerodso it’d be like 30 repeats#2020-01-1317:01mikerodI don’t use all 30 of these things#2020-01-1317:01borkdude(ns foo {:clj-kondo/config '{:linters {:unresolved-symbol {:level :off}}})#2020-01-1317:01mikerodso so far I’ve just blacklisted the ones I do use in the config#2020-01-1317:01mikerodsince that is less#2020-01-1317:01mikerodI didn’t know that was an option - it is appealing from within the ns for sure#2020-01-1317:01mikerodtypically no other ns will try to use these autogenerated ones#2020-01-1317:01mikerodbut they can still#2020-01-1317:02borkdudein that case they won't get reported, if they are coming from another namespace#2020-01-1317:02mikerodoh, it ignores things like other/auto-foo ?#2020-01-1317:02borkdudeyeah#2020-01-1317:02mikerodthat certainly improves the situation for me#2020-01-1317:03mikerodI’m a little surprised I guess since perhaps people may want to know if they are referring to bogus symbols in other ns’s though#2020-01-1317:03mikerodguess it’s just a tradeoff#2020-01-1317:04mikerodother/typo-foo ;; <-- uh oh#2020-01-1317:04mikerodis it just that the compiler will tell you that anyways?#2020-01-1317:05borkdudethere is an issue for it to make this work: https://github.com/borkdude/clj-kondo/issues/634 it's just not there yet and I'm not sure if we should ever do this. feel free to respond in that ticket with your opinion#2020-01-1317:05borkdudegiven that clj-kondo might not have a complete picture of your "other-ns", it will probably lead to false positives#2020-01-1317:09mikerodYeah in my case with this sort of macro I think it’d be pretty bad for me on false positives now that I think of it. #2020-01-1317:09borkduderight#2020-01-1317:09mikerodThanks for the issue link. Will post any more thoughts there. #2020-01-1320:12Aleedcould clj-kondo be used to configure code completion? i ask b/c what think i'll miss about Typescript/Static Typing isn't necessarily error detection but improve Intellisense#2020-01-1320:14borkdudeI believe @sogaiu has developed some tooling for emacs using the clj-kondo analysis output#2020-01-1320:14borkdudebut in general runtime tooling like CIDER/orchard can do this as well#2020-01-1320:14borkdudemaybe sogaiu could post a link to his work#2020-01-1320:17sogaiuthe following instructions are for use with emacs: https://gist.github.com/sogaiu/6cb947b00ae13d00d4ae16ab7aaf97e4 but there is a piece that can generate either a TAGS (etags) or tags (ctags) file. i have used the ctags version successfully with vscode (but i needed to add an appropriate plugin for it). i've also used it with atom, but there the built-in "jump-to" functionality appears to be on the broken side.#2020-01-1320:18sogaiui haven't tried to get the generated content to work with completion (on vscode and atom) -- i'm not sure what is involved.#2020-01-1320:18sogaiuso to be clear, the focus so far has been on navigation.#2020-01-1320:19borkdude@sogaiu why not add that gist to the README of the repo?#2020-01-1320:19sogaiubecause i have not received enough feedback 🙂#2020-01-1320:21sogaiudoes the clj-kondo lsp stuff do code completion?#2020-01-1320:21borkdudeno only linting, same as the .exe#2020-01-1320:21sogaiuah i see#2020-01-1320:22Aleedthe linked file is only navigation, correct? also, i'm using vscode so maybe I'd be more appropriate for me to continue discussion there? just thought that clj-kondo might be a more generic way of adding this feature since calva already uses it for linting#2020-01-1320:22borkdude@alidcastano calva only bundles the clj-kondo vscode plugin, but doesn't really interact with it on a program level#2020-01-1320:24sogaiuthe link is to a description that explains how to get navigation to work for emacs (though as a side effect, it may allow other things). there are both #calva-dev and #vscode if interested in discussing in other places 🙂#2020-01-1505:38sogaiufwiw, i got a bare-bones vscode extension that uses the generated ctags file to provide completion. the main drawback currently is that this uses node-ctags which is a native node module.#2020-01-1322:10borkdudeSmall "critical" update with regards to with-redefs: https://github.com/borkdude/clj-kondo/releases/tag/v2020.01.13#2020-01-1414:53aviSorry if this is a FAQ, but kondo always produces unresolved symbol errors when I open up my deps.edn file in my editor. Is there a known workaround for this? Or a plan to change it? I don’t quite understand the behavior, given that the EDN spec says symbols are valid in EDN files, and AFAIK there’s no way within the file to provide a way for the symbols to be resolved…#2020-01-1414:54borkdudedoes it also happen when you lint the file from the command line?#2020-01-1414:56avichecking…#2020-01-1414:56avinope#2020-01-1414:56aviconfusedparrot#2020-01-1414:56avi(I’m using Atom with linter-kondo)#2020-01-1414:57borkdudemaybe linter-kondo doesn't pass the right --lang argument when it lints a .edn file. It should pass --lang edn#2020-01-1414:59aviah, OK, I’ll take a look. Thanks!#2020-01-1415:00aviit doesn’t look like it’s passing --lang at all…#2020-01-1415:00aviwhich from my CLI testing, I would think, should not yield errors?#2020-01-1415:00avi
$ clj-kondo --lint deps.edn 
linting took 18ms, errors: 0, warnings: 0
#2020-01-1415:00avihttps://github.com/gerred/linter-kondo/blob/master/index.js#2020-01-1415:02borkdudeit passes the text via stdin, so clj-kondo doesn't know the filename. so it cannot know if your code is edn, clj, cljs etc#2020-01-1415:02borkdudethis is what the --lang flag is for#2020-01-1415:03aviaha, so I need to add --lang to the plugin. OK, I’ll give that a try. Thanks!#2020-01-1415:03borkdudeyeah which is basically just the file extension#2020-01-1420:32avi… I opened a PR: https://github.com/gerred/linter-kondo/pull/2 — it might even work! (I haven’t tested it 😬 😅)#2020-01-1421:03borkdudecool!#2020-01-2120:56practicalli-johnI am assuming clj-kondo does a one pass analysis of the code. So if a function is called before it's defined, then it is marked as not found. I think I saw this for the first time today, when using clj-kondo with Emacs. Just curious if this assumption is correct. I get so used to the REPL let me do any order in the source code file so as long as things are evaluated in the running REPL.#2020-01-2121:06borkdudeThat's true, one pass, just like Clojure itself#2020-01-2121:55yuhanSame here, I usually have rich comment blocks scattered around the source file as REPL experiments / documentation, and which reference functions defined much later in the file - there I insert (declare <function>) in the comment block to get around clj-kondo's warnings#2020-01-2215:48bfabryidea: inspection that warns about a function definition without ! at the end of the name that includes a call to a function with ! at the end of the name in the body#2020-01-2220:54eraserhdI don't think ! has a consistent meaning in Clojure.#2020-01-2220:55eraserhdAlso, it's possible for a function to be pure even though it mutates things. e.g. a function which uses transients for performance but returns the persistent collection.#2020-01-2220:56bfabryah, that is a good point#2020-01-2221:00eraserhdidea: warn when two files require a namespace with different aliases?#2020-01-2308:40dominicmI've mentioned this a few times, I have a plan to write something that will rewrite your project into consistency automatically#2020-01-2308:40dominicmI want a few other pieces in place first, namely alignment of forms needs careful preservation. Doing research into that now :)#2020-01-2221:20Adrian SmithIs there an exception for js/ in cljs?#2020-01-2221:30borkdude@eraserhd That feature is already in clj-kondo: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#alias-consistency Although you have to decide on one accepted alias using the config before you get a warning. The analysis output can also help to detect difference and to create the initial config.#2020-01-2221:30borkdude@sfyire Are you sure that's not a cljc file? Can't reproduce it.#2020-01-2221:32Adrian Smith@borkdude oh weird I get it for https://github.com/roman01la/proton-native-cljs using atom and the linter-kondo plugin (inside core.cljs)#2020-01-2221:53borkdude@aviflax was going to do a PR to fix this I believe. it's doesn't pass the --lang flag so clj-kondo doesn't know this is cljs#2020-01-2221:54borkdudeit seems the commit is already in there, so maybe try upgrading the plugin @sfyire? https://github.com/gerred/linter-kondo/blob/master/index.js#2020-01-2221:55borkdudeor maybe it hasn't been released yet. anyway, that's the issue#2020-01-2221:58Adrian Smith@borkdude oh I see that might be why I don't see that error in cursive, looks like they haven't tagged up a release yet in linter-kondo, good to know it's incoming though#2020-01-2221:58borkdudemight be worth asking the maintainer(s) directly#2020-01-2221:59borkdudecc @gerred#2020-01-2221:59gerred👋#2020-01-2221:59gerredPR me! 🙂 I'm underwater with work right now.#2020-01-2221:59gerredor open an issue and I can look in the next few days#2020-01-2222:01borkdude@gerred It's about this PR https://github.com/gerred/linter-kondo/pull/2#issuecomment-574752149 which isn't released yet#2020-01-2222:01gerredoooh ok.#2020-01-2222:01gerredone sec, on a call then I'll review. do I need to cut a release?#2020-01-2222:02borkdude@gerred avi mentioned: > but first one of us should test this change in the last comment of that issue. 🙂#2020-01-2222:02borkdudemaybe there's also a way for people to build the plugin locally to test it out#2020-01-2222:03Adrian SmithI have an example of a failing test case but not sure how to build the plugin locally, will do some googling#2020-01-2222:08Adrian Smithok so I've uninstalled the existing plugin, done git clone ~/.atom/package/linter-kondo/ and I can see the plugin in atom's list#2020-01-2222:08Adrian Smithnow there's no error but also don't see anything when adding (inc "test") so I think I may have done something wrong#2020-01-2222:08Adrian SmithI did see other people talking about using apm link#2020-01-2222:19Adrian Smithah figured out why, I usually disable toasts but it does hide important stuff:#2020-01-2222:19borkdudemaybe someone in the #atom-editor channel knows how to build such a thing?#2020-01-2222:19Adrian Smiththis isn't a bug in the linter it's something I've done to try and load it in dev mode#2020-01-2222:20borkdudeoh, only 16 people there#2020-01-2222:21borkdudegood luck, I'm afk now#2020-01-2222:33Adrian Smithok I've figured out a couple of things, the above error I needed to npm i but I'm still not seeing anything when I console log that line I get:#2020-01-2222:34Adrian Smithlooks like clj-kondo expects cljs instead of .cljs for that argument, I've "fixed" that locally but that doesn't appear to have fixed it#2020-01-2222:35borkdudeit's supposed to be --lint - --lang cljs so it's also the wrong order#2020-01-2222:37Adrian Smithgood spot that's working in a local hack#2020-01-2222:56Adrian Smith@gerred I think this might be what we're after: https://github.com/gerred/linter-kondo/pull/3#2020-01-2223:20gerred@sfyire thank you! Still on this call :face_with_rolling_eyes: then I'll look and merge, and throw you a commit bit.#2020-01-2223:57aviAh, sorry… I meant to look into how to test that change but I haven’t gotten around to it#2020-01-2300:11gerrednw we're all busy 😄#2020-01-2300:17avijust threw a on your PR that fixes my PR 😬#2020-01-2301:53gerredOK longest customer call of my life#2020-01-2301:53gerredi'm looking through all of this now#2020-01-2301:54gerred@aviflax did you check if you were able to cut a release?#2020-01-2301:59aviI didn’t because I was waiting for ~you~ one of us to test it#2020-01-2302:00aviI can give it a try now if you’d like?#2020-01-2302:00aviEr, or, in the next hour or two#2020-01-2302:00avi@gerred either way is fine, let me know#2020-01-2302:02gerredgive it a try first, just so we can make sure we can split the load. 🙂#2020-01-2304:44aviDone, and it worked. The release process worked — my editor picked up on the update immediately. And the new feature works too!#2020-01-2304:44aviThanks!#2020-01-2313:00gerrednp!#2020-01-2313:00gerred@UCJCPTW8J would you like to be made a collaborator too?#2020-01-2313:05Adrian Smith@gerred yeah that'd be cool, thank you#2020-01-2313:41otwieraczHey, any ideas how can I tell clj-kondo to ignore errors like here:#2020-01-2313:42otwieraczI've got this exclusion to prevent action from causing an error, but it still gives me false positives below.
:linters {:unresolved-symbol {:exclude [(com.fulcrologic.fulcro.mutations/defmutation [action remote ok-action error-action])]}}}
#2020-01-2313:53borkdude@slawek098 Seems to work here:#2020-01-2313:54borkdudewhat is the warning about state?#2020-01-2313:56otwieracz
unresolved symbol state
#2020-01-2313:56borkdudeyou just need to add state to that vector as well, or just leave the vector empty, so it will ignore all unresolved symbols#2020-01-2313:56borkdudeI mean, leave the vector out#2020-01-2313:57borkdudeLike so:#2020-01-2313:57otwieraczThis helped. Thanks!#2020-01-2511:52Janne SauvalaWhich way do you recommend to use kondo with Intellij: LSP server or File Watchers + installed binary? Or does it make any difference which I choose?#2020-01-2513:19borkdude@janne.sauvala Some reported that the LSP server was a better experience for them. But it can't hurt to try both#2020-01-2515:40Janne SauvalaI tried first with the LSP server but the plugin has some problems with the IDE. It was crashing to some platform API calls. With File Watcher kondo works and I prefer it over LSP because it would always use the latest version of kondo (I installed and update it with brew)#2020-01-2515:48borkdudeok!#2020-01-2600:49jvtriguerosI recently switched to the LSP version because I noticed a slight lag when typing. I don’t see this lag with LSP. Both work great!#2020-01-2608:10Janne SauvalaI’m using Intellij 2019.3.2 and downloaded the LSP plugin from the IDE’s marketplace and the plugin crashed to an exception. Are you using the same setup?#2020-01-2620:14jvtriguerosYou must get the unreleased version from the same author. The one from the marketplace doesn't work with the latest version of clj-kondo#2020-01-2620:15borkdudeMaybe the jar I just posted does#2020-01-2620:15borkdudeNot sure, but I made some changes regarding end locations.#2020-01-2620:16jvtriguerosI turned on logs in IntelliJ but it wasn't enough to tell me why it wasn't working.#2020-01-2620:24jvtriguerosOk, just tried the SNAPSHOT with LSP version 1.5.4 and it's not working, let me upgrade manually to 1.6.0#2020-01-2620:24borkdudethanks#2020-01-2620:24borkdude1.6.0 is still not available in the marketplace?#2020-01-2620:25jvtriguerosNot yet. It's still pending.#2020-01-2620:25borkdudepff#2020-01-2620:26borkdudeIf you're testing the SNAPSHOT, please pay attention to misplaced squiggles#2020-01-2620:27jvtrigueroskk, one sec restarting IJ for the 5th time :D#2020-01-2620:28jvtriguerosOk confirming that LSP 1.6.0 works with the SNAPSHOT. I'll move off this thread to report issues (if any with LSP+kondo)#2020-01-2620:28borkdudethanks! ❤️#2020-01-2620:12borkdudeAnyone using the LSP server, please test this new server before I release it into the wild:#2020-01-2620:12borkdude(cc @jvtrigueros)#2020-01-2620:29jvtriguerosThe squiggles are now on the parens, is that by design?#2020-01-2620:30jvtrigueros~wait wait I haven't upgraded, false alarm~ sorry I did upgrade, just got confused above still holds#2020-01-2620:34borkdudeI don't know what was the behavior before, but now it's the same as emacs, which isn't bad imho:#2020-01-2620:34borkdudeBefore clj-kondo only reported the start location and the editor had to make sense from that only where to put the squiggles#2020-01-2620:35borkdudeOne issue I solved after introducing this was that the entire sexpr would be squiggled which is quite annoying.#2020-01-2620:48jvtriguerosLet me revert and compare#2020-01-2620:49jvtriguerosSo before it used to be like this:#2020-01-2620:50jvtriguerosI don't know if this is LSP or clj-kondo, but when I was using watchers it wouldn't change the syntax colouring but with LSP it removes it and just gives me the default text color.#2020-01-2620:51jvtriguerosThis is usually for things I gotta fix, but for macros like specter, I have to keep this around:#2020-01-2620:52jvtriguerosI'll keep using the SNAPSHOT and see if there's any more differences. I just switched to the LSP version so I may miss some of the differences 😄#2020-01-2621:01borkdude@jvtrigueros Don't know what's with the syntax colouring, but it seems clj-kondo has an issue with that macro. In that case you should / could use a config to get rid of those warnings.#2020-01-2621:24jvtriguerosI’ll do that! #2020-01-2710:35borkdudeclj-kondo v2020.01.27: better detection of missing test assertions and other enhancements. https://github.com/borkdude/clj-kondo/releases/tag/v2020.01.27#2020-01-2812:52Nico HarttoHello @borkdude, thank your for the great tool first and foremost :) I'm trying to get LSP server working with clj-kondo-lsp-server-2020.01.13-standalone.jar and IntelliJ IDEA 2019.3.1 + LSP Support 1.6.0 (+ Cursive) as per https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#lsp-server-1. For reason or another, when trying to set {:lint-as {nedap.speced.def/defn clojure.core/defn}} in .clj-kondo/config.edn to resolve speced defn as defn it does not seem to work. Simple things like linting (inc "a") work as expected. Is there something I'm missing in the configuration/misconfiguration or is there a way to debug this in someway?#2020-01-2812:55borkdude> thank your for the great tool thanks! > it does not seem to work can you try to reproduce this using a command line invocation, as that excludes issues with other tooling can you also give a bit more information than "it does not work"? :)#2020-01-2813:11Nico HarttoHere's how it shows up on idea when I have LSP running. Normal defn just shows the "typo" green, but for speced/defn I'm getting red underlining which does not happen without clj-kondo. When LSP server raw command is removed, both show without red underlining. Not working might be overstatement, but it's visually less appealing this way.#2020-01-2813:13borkdudeCan you reproduce this using a command line invocation?#2020-01-2813:18borkdudee.g.:
$ clj-kondo --lint - --config '{:lint-as {nedap.speced.def/defn clojure.core/defn}}' <<< "(ns foo (:require [nedap.speced.def :as speced])) (speced/defn destructuring-example [{:keys [^string? a] :as ^::thing all}])"
<stdin>:1:104: warning: unused binding a
<stdin>:1:120: warning: unused binding all
#2020-01-2813:18borkdudeThat seems to work perfectly.#2020-01-2813:19borkdudeMaybe you do not have the alias speced since that's also underlined in your screenshot#2020-01-2813:36Nico HarttoIt's just for the "typo warning", but I will try with the cli option to see what's-what#2020-01-2813:56thumbnailThis is my lint-as option map btw:
:lint-as '{nedap.speced.def/def-with-doc clojure.core/defonce
              nedap.speced.def/defn         clojure.core/defn
              nedap.speced.def/defprotocol  clojure.core/defprotocol
              nedap.speced.def/doc          clojure.repl/doc
              nedap.speced.def/fn           clojure.core/fn
              nedap.speced.def/let          clojure.core/let
              nedap.speced.def/letfn        clojure.core/letfn}
#2020-01-2814:16borkdude@UHJH8MG6S and I assume that works for you?#2020-01-2814:17thumbnail@borkdude it does, but i run the formatter using the clj-kondo.core/run! api, no LSP setup here.#2020-01-2815:46borkdudeMaybe the editor is not picking up your config because of the current working directory your in @USR9PTXHB#2020-01-3110:07Nico HarttoWorks now, it must be that my IDEA setup was different for this project. It works on a different project as expected. Thank you all for the input & help 🙂#2020-01-3110:10borkdude❤️#2020-01-2815:23borkdudeThe next clj-kondo will have a new (optional) linter that checks if namespaces are sorted. Thanks @helios#2020-01-3110:18borkdudeMy Github sponsors profile just went live! If you're using clj-kondo and want to show your support, here's a way. Even if only for 1 dollar a month, it helps sustain this project. https://github.com/sponsors/borkdude#2020-01-3111:43borkdudeThat's right, now I will become rich! Of course clj-kondo remains free and I will love you just as much even if you don't become a sponsor ❤️#2020-01-3112:09dominicm<maniacal laugh gif>#2020-01-3122:32borkdudeThe clj-kondo Visual Studio Code extension reaches 10.000 installs! https://marketplace.visualstudio.com/items?itemName=borkdude.clj-kondo#2020-02-0116:29Adrian SmithI'm trying to use clj-kondo on emacs I've installed the extension via package-install and added (require 'flycheck-clj-kondo) to my init.el but nothing lints unless I run :global-flycheck-mode in evil mode, then it works but that's not persistent, what am I missing?#2020-02-0116:43Adrian Smithah I think (global-flycheck-mode 1) in init.el has "fixed" it#2020-02-0117:03borkdudefollow the instructions here: https://www.flycheck.org/en/latest/#2020-02-0117:51borkdudeI've got a clj-kondo build here which adds type checks for function calls: https://8273-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2020.01.28-SNAPSHOT-linux-amd64.zip https://8275-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2020.01.28-SNAPSHOT-macos-amd64.zip It's probably not perfect yet, but what it catches at the moment is for example:#2020-02-0117:51borkdudeWelcome to test it out on more examples and report non-working ones.#2020-02-0122:47borkdudeyeah, it's hacky but linting as cljs.test/async works 🙂#2020-02-0122:51practicalli-johnI have to say thanks again to clj-kondo. I had several tips of really useful feedback during my live coding broadcast today. clj-kondo feels like I am constantly pairing with a trusted friend who lovingly stops me from making silly mistakes and helps me write more idiomatic code. (and this is with a version that's a couple of months old).#2020-02-0122:53borkdudeI did find a type error in a proprietary project just now, but it was probably in some unused code:#2020-02-0205:54sogaiuyeah, that's the explanation i've ended up with repeatedly when i've had behavior i didn't expect :)#2020-02-0309:39borkdude#2020-02-0310:25borkdude@marc-omorain excerpt from our work slack:#2020-02-0310:26Marc O'Morain👌👌👌 delighted to have helped someone out. That feature was born from my own frustration with Clojure’s errors for that case. #2020-02-0413:41Ian Fernandezhow I config the "root" kondo for emacs lsp-mode use a lint-as config?#2020-02-0413:54borkdude@d.ian.b The .clj-kondo/config.edn lives in the root of your project.#2020-02-0413:55Ian FernandezI need to restart lsp server to re-detect the config.edn?#2020-02-0413:56borkdudeno, I think the lsp-server should set the current working directory for the file you're editing#2020-02-0413:57borkdudefor example in Visual Studio Code you can open a directory and edit files. then the current working directory for plugins becomes that directory#2020-02-0414:05borkdude@d.ian.b If something does not work as expected, you can hack on the LSP server and add some logging. The code is here: https://github.com/borkdude/clj-kondo.lsp#2020-02-0414:05Ian Fernandezthanks!#2020-02-0414:47otwieraczDoes clj-kondo should warn about non-existant namespaces?#2020-02-0414:50borkdude@slawek098 it does warn about namespaces that you are trying to use but you haven't required. but it does not check if the namespace exists somewhere on disk#2020-02-0414:52otwieraczok#2020-02-0614:11geraldodevExpected collection, received transducer, so sweet !#2020-02-0614:13borkdude😄 ❤️#2020-02-0716:19borkdude#2020-02-0716:32borkdudehttps://8456-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2020.01.28-SNAPSHOT-linux-amd64.zip https://8455-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2020.01.28-SNAPSHOT-macos-amd64.zip
#2020-02-0716:33borkdude^ if you want to play with the above. this contains return type inference for functions, and inference of if, if-let, when and when-let expression#2020-02-0719:22borkdudeAlso added clojure.core/or:#2020-02-0813:08practicalli-johnIsclj-kondo able warn about using a macro as a function argument, eg. (apply and [,,,]). I have only done this once recently, so not sure how useful this is.#2020-02-0813:11borkdudethere is an issue for this, but it's not implemented yet#2020-02-0813:12borkdudehttps://github.com/borkdude/clj-kondo/issues/380#2020-02-0915:41borkdude@tatut Maybe you have some input on this, since you came up with the issue: https://github.com/borkdude/clj-kondo/pull/747#issuecomment-583858700#2020-02-1014:45Sasho👋 Hello. Does anyone know where I can find a full list of all the linters, that clj-kondo has?#2020-02-1014:46borkdudeHi, @sasho.popov welcome! All linters are enabled by default, except these: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#enable-optional-linters Here you can at least see all the names: https://github.com/borkdude/clj-kondo/blob/c590e59b24505e58fc7f5eb252780a387d02f88b/src/clj_kondo/impl/config.clj#L7#2020-02-1014:50SashoThank you, this is exactly what I needed. The idea is that I want to disable some warnings, but I need the exact name of the linter in order to add it to the config.#2020-02-1014:50borkdude:thumbsup: One other way to discover the right keys with each warning is to use JSON or EDN output#2020-02-1014:51SashoBut I don’t invoke clj-kondo manually, I use it via calva and I see the warnings in the Problems tab of Visual Studio Code.#2020-02-1014:51borkdudeJust out of curiosity, which linters do you disable?#2020-02-1014:52SashoUnresolved namespace clojure.pprint. Are you missing a require?#2020-02-1014:53SashoAlso use seq instead of (not (empty? ,,,)#2020-02-1014:53borkdudeIs that a false positive or did you really forget a require?#2020-02-1014:54borkdudeIn case of false positives, I'd like to receive issues for them, to improve clj-kondo#2020-02-1014:54SashoO.K., so I’m new to clojure and I don’t know what the best practice for this is, but why do I need to require something, when I can reference it with full namespace?#2020-02-1014:54borkdudeBecause the namespace might not have been loaded yet.#2020-02-1014:54SashoMeaning it will give me a runtime error?#2020-02-1014:55borkdudeYes. Most tooling will load clojure.pprint already but you can not rely on that implicitly. $ clojure -e "(clojure.pprint/pprint {})" Execution error (ClassNotFoundException) at https://java.net.URLClassLoader/findClass (URLClassLoader.java:471). clojure.pprint#2020-02-1014:56borkdudeIn doubt, ask Alex Miller about this, he will tell you the same 😉#2020-02-1014:56SashoO.K., a couple of noob questions. clojure.pprint -> this is not part of clojure.core, obviously, right?#2020-02-1014:56borkdudeit is part of the standard library of clojure but not everything in the standard library is pre-loaded#2020-02-1014:57borkdudeand you should never rely on anything but clojure.core to be already loaded#2020-02-1014:57borkdude(clojure.core, the namespace, clojure.pprint is a different namespace)#2020-02-1014:57SashoAha, ok, so when I start a clojure program, is automatically pre-loads clojure.core , but nothing else (unless I require it explicitly, of course).#2020-02-1014:58borkdudeyes, or unless any other of your REPL tooling is loading that, but again, you should not trust on that, because if you release an uberjar for example, this tooling won't be there anymore#2020-02-1014:58SashoO.K., in that case, instead of disabling the linter, I might as well fix the offences 😉#2020-02-1014:58SashoThank you for taking the time to explain this to me. 🙂#2020-02-1014:59borkdudeNo problem. It's always worth digging a little deeper to see why people are doing stuff.#2020-02-1015:02Sashothanks3#2020-02-1014:47borkdudeThis should probably be documented... 🙂#2020-02-1014:50SashoThe source is ok for this particular case, although something like https://docs.rubocop.org/en/stable/ would be nice. 🙂#2020-02-1109:48borkdudeIn progress:#2020-02-1109:49borkdudeNew on master:#2020-02-1215:30jjttjjsci should be safe for execution of untrusted code right? ie a public cljs client sending sci strings to a clj server for evaluation#2020-02-1215:35borkdude@jjttjj let's talk in #babashka about this#2020-02-1215:37jjttjjgood call thanks!#2020-02-1316:35DerekA co-worker is having trouble in VSCode with the bundled clj-kondo linter seeming not to respect a local .clj-kondo/config.edn file#2020-02-1316:37borkdudeI think plugins in VSCode get the current working directory from the current workspace #2020-02-1316:38borkdudeSo if you’re editing files outside of that, that may not work. Could that be the problem maybe?#2020-02-1316:38DerekI’ll ask her to check#2020-02-1316:38borkdudeCould also be a typo. Repro welcome.#2020-02-1316:40DerekThat’s all it was. Thanks so much#2020-02-1317:03borkdudethanks!#2020-02-1317:03borkdude@dpassen1 what was it btw, the working dir or the typo?#2020-02-1317:09Derekthe working directory#2020-02-1317:10DerekThe rest of us on the team either use emacs and flycheck or vim and ale and it has all worked so smoothly for us#2020-02-1317:11borkdudethere used to be a patch in clj-kondo that when linting a single file it starts looking from the parent dir of that file, but that was only a workaround for a specific editor it might make sense for these cases, but in general the workspace thing works I think#2020-02-1317:11borkdudeemacs flycheck already sets the working directory to the parent of the file#2020-02-1317:12borkdudealso the LSP plugin doesn't even see the filename, so it's a bit tricky to apply it in that case. if you know how it works, it's not a problem I reckon#2020-02-1318:17dominicmI don't seem to have :import data in the kondo analysis, {c,sh}ould I?#2020-02-1318:48borkdude@dominicm I guess we could. PR welcome#2020-02-1318:51borkdudethere is a namespace clj-kondo.impl.analysis where all data that is collected currently goes through#2020-02-1318:54dominicmCool. Will add to my list 🙂#2020-02-1401:07sogaiuthat would be nifty!#2020-02-1407:07dominicmI've written something for doing namespace->dependencies, but it is marking some things as completely unused due to them being java#2020-02-1418:32dominicmI'm getting this:
Execution error (ClassCastException) at clj-kondo.impl.core/filter-findings$iter$fn$fn$fn (core.clj:285).
class java.io.File cannot be cast to class java.lang.CharSequence (java.io.File and java.lang.CharSequence are in module java.base of loader 'bootstrap')

Full report at:
/tmp/clojure-15340904493825742425.edn
When running clj-kondo analysis on cljdoc/cljdoc on github.
#2020-02-1418:34borkdude@dominicm Could be this (fixed) issue: https://github.com/borkdude/clj-kondo/issues/719#2020-02-1418:36dominicm@borkdude next release meaning, next one to hit clojars will have this fix in?#2020-02-1418:38borkdudeyes, you can use as git dep meanwhile#2020-02-1418:38borkdudeor clojars snapshot#2020-02-1418:39dominicmit's np, I found another project to do my demo with.#2020-02-1418:41dominicmhttps://github.com/SevereOverfl0w/vizns This project uses kondo to find the relationships between your project and it's dependencies.#2020-02-1418:50borkdudesweet!#2020-02-1418:51borkdudeso I guess you need the imports for the java false positives?#2020-02-1419:07dominicmYeah, exactly. It won't cover everything (like implicit loaded logback, but a number of other common java libraries could be handled). I guess I'd also need "implicit imports" - use of java without import.#2020-02-1419:09borkdudethere are things in clj-kondo which guess if something is a java class / interop so it won't be reported as a false positive unresolved symbol. I guess that could also go to the used classes#2020-02-1419:09borkdudethere's two things: imported classes and actually used classes. both seem useful to include in the analysis data#2020-02-1419:10borkdudeclj-kondo already knows about it since it can report unused imports#2020-02-1510:43borkdudeclj-kondo v2020.02.15: return type inference, unsorted required namespaces linter and more. thanks to all who contributed. https://github.com/borkdude/clj-kondo/releases/tag/v2020.02.15#2020-02-1811:15FiVoIs there anything special I need to do for flycheck-clj-kondo to pick up a config? The plugin works fine for me in clean project.#2020-02-1811:20borkdude@finn.volkel The config is picked up using the current working directory. Emacs sets the current working directory for flycheck relative to the file you're editing#2020-02-1811:21borkdudeso if you're editing /foo/bar/baz.clj and your config is in /foo/bar/.clj-kondo/config.edn then it should work#2020-02-1811:21FiVothere is a config at the root of the repo#2020-02-1811:22borkdudedoes the config work from the command line?#2020-02-1811:24FiVoyes#2020-02-1811:32borkdudeI'm not aware of any changes you should have to do to flycheck-clj-kondo. I'm using that myself every day#2020-02-1811:35FiVoSolved had to restart emacs from a new session.#2020-02-1811:35FiVoSorry for the hassle#2020-02-1811:35borkdudenp#2020-02-1818:45sparkofreasonIs there some way to set global/default config? Something similar to .clojure/deps.edn.#2020-02-1819:38eggsyntaxI'm also curious about sparkofreason's question. And another quick question -- does .clj-kondo/config.edn replace the default config, or is it merged at the top level, or is it deep-merged? Also thanks for clj-kondo, it brings me joy!#2020-02-1821:02borkdudeit is deep-merged. global/system/user configs are not supported. more info here: https://github.com/borkdude/clj-kondo/issues/736 solution: make a script (use babashka for it!)#2020-02-1821:12sparkofreasonNice. Been looking for an excuse to use babashka. Thanks.#2020-02-1822:22eggsyntaxThanks borkdude!#2020-02-1920:44nateDoes anyone have an example of using a namespace local config to turn off a linter? I can't seem to get it to work.#2020-02-1920:45nateDoesn't work:
(ns 
  {:clj-kondo/config {:linters {:unused-namespace {:level :off}}}}
  (:require
    [foo.bar :as bar]))
#2020-02-1920:51borkdude@nate The config has to be quoted, even if all the stuff in there is keywords#2020-02-1920:52borkdudeThis is what clj-kondo expects#2020-02-1920:52borkdudethen why does Slack suggest the wrong Nate first... stupid app 😉#2020-02-1922:11sogaiuon a related note, i wonder why when i press tab for completing nicks that i end up on completely different candidates than what was already highlighted...#2020-02-1920:56nateSo, like this?
(ns 
  {:clj-kondo/config '{:linters {:unused-namespace {:level :off}}}}
  (:require
    [foo.bar :as bar]))
#2020-02-1920:58borkdudeyes#2020-02-1920:58nateah, tried that and it didn't work#2020-02-1920:58natelet me try a small repro#2020-02-1920:59nateah#2020-02-1920:59nate
$ clj-kondo --lint test.clj
test.clj:4:6: warning: namespace foo.bar is required but never used
linting took 6ms, errors: 0, warnings: 1
#2020-02-1921:01natehm, using an older version (v2020.01.10), maybe that's it#2020-02-1921:01borkdudethat example does work for me, also in the editor.#2020-02-1921:02borkdude@nate Actually, that exact problem got solved in the last release: https://github.com/borkdude/clj-kondo/issues/430#2020-02-1921:04nateaha! that definitely fixed it#2020-02-1921:04natemany thanks#2020-02-1921:05borkdudemaybe a next nice tweak would be to let clj-kondo accept un unquoted config. I'll make an issue for that as well#2020-02-1921:07natecool#2020-02-1921:07borkdudehttps://github.com/borkdude/clj-kondo/issues/763#2020-02-1921:07nateI saw the note about quoting the config in the docs and tried that, but had a user error by not running the latest#2020-02-1921:08borkdudeyeah, so if there's anything not supported in the ns metadata it can probably be fixed without much trouble#2020-02-1921:10nateon a related note, is there a way to configure linting by namespace or namespace regex? my use case is that I have a set of namespaces that all start with fiddle. that I use during development, and I would like them to have slightly different kondo config, like skipping the unused namespaces check. for now, I will just add the metadata like the above, but wondering if there was a way to do it more generally#2020-02-1921:10borkdudeno#2020-02-1921:10borkdudeunless that's supported on a linter basis#2020-02-1921:10natethe issue is that I do use the namespaces in those files, but usually from comment blocks#2020-02-1921:10borkdudenot in general#2020-02-1921:11borkdudebut clj-kondo does lint comment blocks, unless you've turned that off#2020-02-1921:11borkdude
$ clj-kondo --lint - <<< "(ns  (:require [foo.bar :as bar])) (comment (bar/x))"
linting took 11ms, errors: 0, warnings: 0
#2020-02-1921:12nateah, sorry, to be more specific, I usually use #_(...) style instead of (comment ...)#2020-02-1921:12borkdudethen use comment 😛#2020-02-1921:12natedoesn't see the code in the #_ ones, unfortunately#2020-02-1921:12natehehehe#2020-02-1921:13nateI would like to, but I make extensive use of my editor's "run top level form" mapping, and comment blocks ruin that#2020-02-1921:13borkdudeyou can also require those namespaces from the #_(...) blocks instead then#2020-02-1921:14borkdudeunless it's CLJS#2020-02-1921:15nateinteresting idea#2020-02-2012:42tatutanyone used clj-kondo with github actions to lint PRs?#2020-02-2012:43delaguardohttps://github.com/DeLaGuardo/clojure-lint-action#2020-02-2012:44borkdude@tatut there's a couple of them mentioned here: https://github.com/borkdude/clj-kondo/blob/master/doc/ci-integration.md#2020-02-2012:44tatutnice#2020-02-2013:38tatutI'm having trouble with unresolved symbols in my own macro... exclusion doesn't seem to work#2020-02-2013:39borkduderepro?#2020-02-2013:39tatutmy macro has its own binding form which are used in the body... I can actually give you a link example#2020-02-2013:40borkdudeI prefer a repro in the form:
$ clj-kondo --config '{}' --lint - <<< '(defmacro foo [])'
or
$ clj-kondo --config '{}' --lint file.clj
#2020-02-2013:40borkdudewhich makes it less of a hassle to test it out#2020-02-2013:41tatutsure#2020-02-2013:43tatutjust to be clear, it reports errors at the macro uses, not the definition#2020-02-2013:44borkdudethat's mostly where these issues happen. but that can also be repro'd in the same fashion#2020-02-2013:45tatut
$ clj-kondo --config '{:linters {:unresolved-symbols {:exclude [(repro/foo)]}}}' --lint - <<< '(ns repro) (defmacro foo [bind & body] nil) (foo these should not be reported)'
<stdin>:1:27: warning: unused binding bind
<stdin>:1:34: warning: unused binding body
<stdin>:1:50: error: unresolved symbol these
<stdin>:1:56: error: unresolved symbol should
<stdin>:1:67: error: unresolved symbol be
<stdin>:1:70: error: unresolved symbol reported
linting took 13ms, errors: 4, warnings: 2
#2020-02-2013:45tatutIf I understand correctly, none of those symbols should be reported becaus repro/foo has been marked as excluded#2020-02-2013:46borkdude
$ clj-kondo --config '{:linters {:unresolved-symbol {:exclude [(repro/foo)]}}}' --lint - <<< '(ns repro) (defmacro foo [bind & body] nil) (foo these should not be reported)'
<stdin>:1:27: warning: unused binding bind
<stdin>:1:34: warning: unused binding body
linting took 10ms, errors: 0, warnings: 2
typo?
#2020-02-2013:47tatutah, typo in my config... that makes sense#2020-02-2013:47borkdudeI'm thinking of a --diagnose flag for clj-kondo which lists unexpected things from the config#2020-02-2013:47tatutthat would be nice#2020-02-2013:47borkdudeand prints a lot of other stuff to debug#2020-02-2013:48tatutthanks for the help, I had a feeling it might be between keyboard and chair on this end 😛#2020-02-2013:51borkdudenp 🙂#2020-02-2013:52borkdudethe --diagnose flag would also come in handy so I can ask people to paste their configuration in a Github issue#2020-02-2013:52borkdudeand stacktraces, etc#2020-02-2110:06imreI'm not sure if this has ever been discussed, has anyone figured out how to share the clj-kondo config effectively between projects? My current team has serveral projects that share a lot of macros etc that need the same config over and over again. It would be great to be able to use a shared config but keep the ability to add project-specific overrides when needed.#2020-02-2110:07imreperhaps a combination of a git submodule and a custom file that is then passed in as a command line arg to override things?#2020-02-2110:10borkdude@imre In this issue I have suggested writing a script (perhaps using babashka) for merging configs https://github.com/borkdude/clj-kondo/issues/736#2020-02-2110:12borkdude@imre In clj-kondo itself I've been using an #include reader tag, but this is undocumented, just something I've been playing around with: https://github.com/borkdude/clj-kondo/blob/615543df9cd5477f1c5e9ad08629997f402a2889/.clj-kondo/config.edn#L18#2020-02-2110:13borkdudeI'm not sure in what extent it will work for your purposes, but the scripting option will work for sure#2020-02-2110:13imrethat's an aero thing, right?#2020-02-2110:13borkdudesomething I've implemented myself using data readers#2020-02-2110:14imreyou haven't implemented a #merge reader by any chance, have you? 😄#2020-02-2110:14borkdudehmno, but I guess we could...#2020-02-2110:15imreit might need a bit of brainstorming first, I suppose#2020-02-2110:15borkdudeI guess so yes#2020-02-2110:15imrethank you very much for the pointers, I'll have a read through these#2020-02-2110:17imreshared config + include/merge sounds like a declarative enough approach to cover both editor integrations and command line#2020-02-2110:17imrefor our case#2020-02-2112:51mynomotoHi, I thought that clj-kondo reported on undefined vars from other namespaces. Did I imagine things?#2020-02-2112:52borkdude@mynomoto it does report invalid arities from other namespaces, but it doesn't warn if they don't exist. there is an issue for this though#2020-02-2112:53borkdudehttps://github.com/borkdude/clj-kondo/issues/546 https://github.com/borkdude/clj-kondo/issues/634#2020-02-2112:54mynomotoOk, thanks. I guess I'm relying more on clj-kondo than I should 😅#2020-02-2112:54borkdude🙂#2020-02-2122:03borkdude
$ clj-kondo --config '{:lint-as {mount/defstate clojure.core/def}}' --lint - <<< '(ns foo (:require mount x)) (mount/defstate conn :start (x/create-connection x/config))'
linting took 9ms, errors: 0, warnings: 0
#2020-02-2122:04borkdudethis is just by luck, when clj-kondo would have more strict syntax checking for clojure.core/def this would likely give problems#2020-02-2122:05borkdudeyeah. this one also works:
$ clj-kondo --config '{:lint-as {mount/defstate clj-kondo.lint-as/def-catch-all}}' --lint - <<< '(ns foo (:require mount x)) (mount/defstate conn :start (x/create-connection x/config))'
linting took 12ms, errors: 0, warnings: 0
#2020-02-2122:06borkdudethis is a thing designed to catch all def-like things that cannot be mapped unto something else#2020-02-2122:06borkdudeat the cost of not getting some lint warnings inside that call#2020-02-2122:07borkdudenp, silly mistakes happen. that's why I made this tool in the first place 🙂#2020-02-2122:08borkdudegreat to hear 🙂#2020-02-2222:09glenjaminAnyone got a good suggestion for how to make kondo handle these functions? https://github.com/ptaoussanis/nippy/#custom-types-v21#2020-02-2222:11glenjamincurrently gone with
:unresolved-symbol
{:exclude [(taoensso.nippy/extend-thaw [data-input])
           (taoensso.nippy/extend-freeze [x data-output])]}
which works, but relies on me using those exact names. Ideally I’d want to mark that vector as being an argument vector somehow
#2020-02-2222:13borkdudeif you leave the vector out it will ignore all unresolved symbols#2020-02-2304:04sogaiui'm using clj-kondo to examine source files fetched from github (seeded from clojars' feed.clj). one thing i noticed is that there are files that have names that end in .clj, and they appear to be template files. they have sequences of characters like {{name}} in them. it appears that clj-kondo can pick (some?) of these out and display a message like: "error: Invalid keyword: .", which is nice, but there is no string displayed for what the invalid keyword might have been. i noticed similar messages for invalid symbols and tokens do display some string. is it practical to report what string might have been considered invalid?#2020-02-2308:33dominicmIt might be that it is reading it as : followed by {{...}}#2020-02-2308:33dominicmSo the invalid string might be just ""#2020-02-2308:50sogaiuah, that makes sense -- there was another instance (the squirrel file: https://github.com/technomancy/leiningen/blob/master/test_projects/sample-failing/src/nom/nom/nom.clj) where the sequence was a colon followed by a semi-colon. since the line number is there, i guess i can just read the specific line and print that out. thanks @dominicm!#2020-02-2308:52dominicmNp. I'm glad my years of finding ways to make clojure do weird things is useful :)#2020-02-2611:27tzzhHey, I am a huge fan of kondo and have set it up in all my clojure projects 🙂 I was wondering if there plans to add fixers to automatically fix some of the linting errors ? I’ve just set it up on an existing project and the output is errors: 151, warnings: 421 😿 so it’d be really cool if it can do some of the work for me#2020-02-2611:29borkdudeThanks! Carve is an example of a project that uses clj-kondo AND fixes stuff automatically in your code. I suggest you take a look at that. Clj-kondo will be linting only.#2020-02-2611:30tzzhOK amazing I’ll take a look, thank you :thumbsup:#2020-02-2615:12aviI’ve been meaning to try Carve since you first announced it but honestly I forgot… this chat reminded me that it exists. I just tried it out on my project and wow that’s great. Thank you!#2020-02-2615:28borkdudethanks 🙂#2020-02-2622:38sparkofreasonGiven this in config.edn: :lint-as {com.rpl.proxy-plus/proxy+ clojure.core/defrecord}, using proxy+ does not show interface/class symbols as used. So for example:
(proxy+ []
  Combine$CombineFn
  (createAccumulator
   [_]
  ...)
will still give a warning that Combine$CombineFn is unused. Not a big deal nor very surprising, since it would seem to hard to cover this in general, just thought I'd mention it in case there was some other way I should configure or something.
#2020-02-2622:46borkdudeprobably linting as clojure.core/proxy makes more sense?#2020-02-2622:46borkdudeI don't see how the syntax of proxy+ lines up with defrecord exactly#2020-02-2713:50sparkofreasonYou're right, proxy+ doesn't have a name, probably shouldn't have expected it to work in the first place. proxy+ also doesn't have the same syntax as proxy, though I'll give it a try anyway.#2020-02-2713:51borkdudeYou can just exclude unresolved symbols in this macro#2020-02-2714:00sparkofreasonUsing reify instead of defrecord did the trick. Nice!#2020-02-2714:02borkdudeah#2020-02-2622:48borkdudecurrently clj-kondo mostly ignores what's going on inside proxy, but that will likely improve in the future#2020-02-2709:47iGELWe use Math.round in cljs, and clj-kondo complaints about it. There is no Math namespace I can require. What can I do besides using js/Math directly?#2020-02-2709:47borkdudedoes Math/round work?#2020-02-2709:48borkdude
$ plk
ClojureScript 1.10.520
cljs.user=> (Math/round 1.2)
1
#2020-02-2709:51borkdude@igel ^#2020-02-2709:59iGELOh, sorry. I guess we meant to use that 😉 Thank you#2020-02-2711:40robert-stuttafordthe type inference stuff is awesome @borkdude saved me real time today#2020-02-2711:41borkdudecool! can you post the example maybe (or a similar one)?#2020-02-2711:42robert-stuttafordnext time it does, i will!#2020-02-2815:26borkdudeNew clj-kondo release from Berlin with fellow contributor @rahul080327! https://github.com/borkdude/clj-kondo/releases/tag/v2020.02.28#2020-02-2816:05imreOur jenkins seems to be having an issue with the new docker image, as there is no cat command available on it. Apparently the docker workflow jenkins plugin uses cat for some reason: https://github.com/jenkinsci/docker-workflow-plugin/blob/1089131014350e11adfa364d34e7717954350261/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java#L198#2020-02-2816:06imre
.IOException: Failed to run image 'borkdude/clj-kondo:latest'. Error: docker: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"cat\": executable file not found in $PATH": unknown.
	at org.jenkinsci.plugins.docker.workflow.client.DockerClient.run(DockerClient.java:138)
	at org.jenkinsci.plugins.docker.workflow.WithContainerStep$Execution.start(WithContainerStep.java:199)
	at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:286)
	at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:179)
	at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
#2020-02-2816:08borkdudeThe image is now from SCRATCH. Why do you need cat in it?#2020-02-2816:10tanzoniteblackhttps://stackoverflow.com/questions/55369726/jenkins-docker-container-always-adds-cat-command#2020-02-2816:10imreWe don't but the jenkins docker workflow plugin seems to do#2020-02-2816:14borkdudeI think the solution to fix this for jenkins would be to create your own image based and download the clj-kondo binary from the releases page in your own images.#2020-02-2816:16tanzoniteblackthere's also a workaround mentioned in that stack overflow link#2020-02-2816:16tanzoniteblackand a mention that it might be fixed in the latest release of that plugin if you'd like to update and pray that updating something in Jenkins doesn't break everything you care about#2020-02-2816:28imreWe'll have a look, thanks for the suggestions#2020-02-2816:35zarkonesame issue but for github actions: but with tail instead of cat#2020-02-2816:37zarkonemy action setup:
name: Lint project with clj-kondo

on: [push]

jobs:
  lint:
    runs-on: ubuntu-latest
    container: borkdude/clj-kondo:latest
    steps:
    - uses: actions/
#2020-02-2816:38borkdudeWould it be better if we based it on busybox ?#2020-02-2816:40zarkoneprobably could solve this annoying one 🙂 also, on clj-kondo repo i see different error (with @U04V4KLKC action) : COPY failed: stat /var/lib/docker/overlay2/16a7f7d20fb458c8fb4b3a87cec35c19dad2b97c14c5016c5658543373d5c549/merged/usr/local/bin/clj-kondo: no such file or directory#2020-02-2816:41zarkonebut i dont see that any of paths had been changed..#2020-02-2816:43tanzoniteblackthat's the problem I was seeing before using the static binary. The file existed, but when I attempted to run it I got a no such file or directory error#2020-02-2816:44zarkonebut honestly runners should take care about such cases, wierd that jenkins and github don't have this thing taking in account -- if i understand the issue correct.#2020-02-2816:48borkdudeWe are going to try busybox:musl + fix the path#2020-02-2816:49zarkonethanks for fast feedback! and also, i've removed one really hidden mistake in my code last week with help of clj-kondo -- thakns for this as well 🙂#2020-02-2816:57borkdudeThis one should now work: https://hub.docker.com/layers/borkdude/clj-kondo/2020.02.29-SNAPSHOT/images/sha256-520b337167510d686ed5533a88d8dfdca4769b4ba3f83d60f17a561cb9cb0344?context=explore#2020-02-2817:01borkdudeMaking a new release now.#2020-02-2817:01zarkoneworks 🎉#2020-02-2817:19borkdudedocker is now building, should be released in a few minutes. we have to go to a conference dinner now. please notify us of success 🙂#2020-02-2817:19borkdudeThis is the CI build: https://circleci.com/gh/borkdude/clj-kondo/8824#2020-02-2821:49borkdudeSo I think all issues are fixed now?#2020-02-2822:05zarkoneSorry, I also was on conference dinner :) will check, but I tried pre release snapshot docker image -- it worked!#2020-02-2816:00tanzoniteblack@borkdude, I was literally just having an issue yesterday with setting our automated builds to use clj-kondo related to alpine linux (or something we were doing, not sure what entirely, hoping this static version fixes that). What's your recommended way to automatically install the linux static version, since I don't see an obvious way to do it via the normally recommended install-clj-kondo script?#2020-02-2816:03borkdude@tanzoniteblack I would use the link from the releases page and update it every so often#2020-02-2816:05tanzoniteblackthat's what I was writing in to our docker build right now, so works for me 🙂#2020-02-2816:09tanzoniteblack(also, thanks for this awesome piece of software and for fixing a problem you didn't even know I was having the very next day)#2020-02-2816:10borkdude😄#2020-02-2816:35zarkonesame issue but for github actions: but with tail instead of cat#2020-02-2819:23plinshey @borkdude, I having a false positive with #(do []) with redundant do but its not redundant, if I remove the do the call will fail#2020-02-2820:16imreI think in your case using #(vector) could be more idiomatic https://clojuredocs.org/clojure.core/vector#2020-02-2820:20imreAnd it would circumvent the problem#2020-02-2821:48borkdudehttps://clojurians.slack.com/archives/CHY97NXE2/p1582926492044700#2020-03-0211:30plinsoh thanks for the reply and sorry for that!#2020-02-2819:31tanzoniteblackis there a short and sweet list of names of linters and what they do? I see https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/config.clj which lists out the various linters that are available, and I can guess based off the names, but I wasn't sure if I'm just missing a doc somewhere#2020-02-2821:48borkdude@plins Actually I think the error might be coming from some other linter you're using, in clj-kondo this works fine:
$ clj-kondo --lint - <<< '#(do [])'
linting took 16ms, errors: 0, warnings: 0
#2020-02-2821:49borkdude@tanzoniteblack That's the place I link to from the config.md docs#2020-02-2821:49borkdudehttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md#2020-03-0215:28Marc O'MorainIs there a way to tell clj-kondo that a macro is like a let binding? We have a macro that adds a binding like this:
(with-temp-file filename
  (foo (bar filename)))
And clj-kondo warns about the unresolved symbol. I can mark this macro as excluded, but is there a more sophisticated approach?
#2020-03-0215:36borkdude@marc-omorain You can use :lint-as + cljs.test/async (I know, it's weird, but this works)#2020-03-0215:38Marc O'Morainaha, so cljs.test/async has the same pattern, gotcha 👏#2020-03-0215:39Marc O'MorainWe have some macros that expect square braces in the same way, and I lint those as fn#2020-03-0215:50Marc O'MorainI think I’ve found a false positive case in clj-kondo, going to reduce it down now#2020-03-0215:55Marc O'Morain
(fn unresolved-symbol-x
  [x & {:keys [y]
          :or {y (inc x)}}]
  (+ y x))
#2020-03-0215:56Marc O'Morainlogging in GH now#2020-03-0215:59borkdudewhat is the issue, can you explain in words first?#2020-03-0216:00borkdudeoh I see#2020-03-0216:01borkdudeI'll check in Clojure if this is supposed to work at all 😉#2020-03-0216:03Marc O'Morainlogged as https://github.com/borkdude/clj-kondo/issues/782 thumbsup_all#2020-03-0216:05iGELWe have defined a method called zero? in our money lib, but now clj-kondo complains because we overwrite zero? from cljs.core. Is there a way to white list just these occurrences as OK, possibly similar to rubocop's rubocop:disable comments? I'd prefer not to disable this linter globally if possible#2020-03-0216:06borkdude@igel The canonical way to do this is to use :refer-clojure :exclude [zero?]#2020-03-0216:06borkdudethis is supported by clojure / clojurescript itself#2020-03-0216:07Marc O'Morain
Clojure 1.10.1
(defn foo [x & {:keys [y] :or {y (inc x)}}]
  (+ y x))
#'user/foo
user=> (foo 1 :y 10)
11
user=> (foo 1)
3
#2020-03-0216:07borkdude@marc-omorain I've had more edge cases where people did weird things with or that accidentally worked but were confirmed by the core team as a thing to not rely on, that's why I'm going to ask in #clojure first#2020-03-0216:07Marc O'Moraingotcha#2020-03-0216:08iGEL@borkdude, Thanks, didn't knew that 👍#2020-03-0217:06Marc O'Morain@borkdude so pulling circleci/circle up the latest clj-kondo reported 4 issues. 2 legit bugs, that issue above ^, and a weird case of us abusing name-spaces to break a circular dependency between two namespaces, which clj-kondo can’t deal with (which I don’t expect it to deal with).#2020-03-0217:07Marc O'MorainOne bug was us passing a vector of 4 items as the last arg to clojure.set/union . The other was genuine broken code that happens to not crash.#2020-03-0217:12borkdude@marc-omorain Cool, so all good now? 🙂#2020-03-0218:33Marc O'MorainYup#2020-03-0218:53tanzoniteblackthe lsp plugin with intellij doesn't seem to be reading the project's .clj-kondo/config.edn`, is there a way to convince it to do this?#2020-03-0218:53borkdude@tanzoniteblack I think this depends on the working directory. so if you edit files within your project while your project is opened in its base directory, then it will probably work#2020-03-0218:54borkdudesame for VSCode#2020-03-0219:03tanzoniteblackah, I had to move the config from the module directory I was working in to the project directory, and then restart intellij before it actually kicked in#2020-03-0219:04borkdudeif this is something worth documenting for other users, PR welcome#2020-03-0408:42dharriganI'm using expectations.clojure.test and I'm getting a lint error - perhaps because of the macro usage. Can I tell clj-kondo to ignore?#2020-03-0408:43dharrigan#2020-03-0408:43dharriganerror: unresolved symbol extract-lat-lng-from-#2020-03-0410:10borkdude@dharrigan Can you please post code along with the screenshot, so I can see what it looks like and test it?#2020-03-0410:11borkdudeI suspect {:lint-as {foo/defexpect clojure.test/deftest}} will work#2020-03-0410:12dharrigansure, let me try your suggestion first 🙂#2020-03-0410:51dharriganThanks @borkdude. I had my clj-kondo configuration in the wrong location (home directory, not in the local project folder)#2020-03-0410:51dharrigan.#2020-03-0413:04borkdude@suomi.esko informed me that it's possible to use https://github.com/gregsh/Clojure-Kit/ to set up clj-kondo integration in IntelliJ IDEA#2020-03-0413:04borkdudeI haven't tried it, but if someone wants to and wants to document it, here's the issue: https://github.com/borkdude/clj-kondo/issues/786#2020-03-0417:08oliyHi, I have some imports in my ns declaration that are unused, but they have side effects (logback). It looks like that linter can't be configured. Should I raise a GitHub issue?#2020-03-0417:09oliyBy the way clj-kondo is great, I am impressed by how much more it covers than Joker which I was using before#2020-03-0417:09borkdude@oliy if you are requiring those namespace only for side-effects, you should not give them an alias or use refer and then the linter doesn't warn about them#2020-03-0417:09oliyThey are not clojure namespaces, they are java classes#2020-03-0417:09borkdudeimports do not have side effects#2020-03-0417:10borkdudethanks for the compliment btw#2020-03-0417:10oliyThe class must have a static block or something#2020-03-0417:11oliyThe information I have at the moment is that if we don't import them then logback doesn't work#2020-03-0417:11oliyI can give you more info tomorrow on the specific classes?#2020-03-0417:11borkdudethat isn't correct. importing is only syntactic sugar, it does not have an effect on class loading#2020-03-0417:12oliyOk I'll dig a bit deeper, thanks for your help#2020-03-0615:56oliyHi, me again. I've found a false positive pair in unused binding field and unresolved symbol field with this:
(defn foo [k {v k}] v)

(foo :a {:a 1}) ;; -> 1

#2020-03-0615:57oliy(both instances of k are highlighted respectively)#2020-03-0616:00borkdude@oliy don't do this. https://github.com/borkdude/clj-kondo/issues/782#2020-03-0616:01oliyAh thank you, I searched but it was hard to know how to describe the code :)#2020-03-0616:01borkdudeIf you think this is supported by Clojure (and not just accidental behavior) talk to Alex Miller or anyone else from the core team. If they think it should be supported as official Clojure, I would be happy to fix it.#2020-03-0616:01borkdudeBut as of now it seems they don't support it.#2020-03-0616:01oliyYeah I find it hard to read myself so I'm not a fan of it, but it is wonderfully terse#2020-03-0616:01oliyI'll just rewrite#2020-03-0616:03borkdudeI pasted this convo over there now: https://github.com/borkdude/clj-kondo/issues/782#issuecomment-595835968 In case anyone else searches for it.#2020-03-0621:47dominicmI work on the same codebase as oliy. I'm so glad that code can be killed now. I was shocked & horrified when I found it.
#2020-03-0914:54Sasho👋 Is clj-kondo able to work with macros, that expect a binding vector. Here’s an example: https://github.com/clojure/java.jdbc/blob/2acbf2736a30634c9c75e6a1853e970ffa6bdbb4/src/main/clojure/clojure/java/jdbc.clj#L876 When I write:
(jdbc/with-db-connection [db some-db-spec] …)
clj-kondo complains tha db is unresolved (`unresolved symbol db` )
#2020-03-0914:55borkdude@sasho.popov You can probably use :lint-as {clojure.java.jdbc/with-db-connection clojure.core/with-open}#2020-03-0915:10SashoMichiel, is this a valid config?
{:lint-as {clojure.java.jdbc/with-db-connection clojure.core/with-open
           clojure.java.jdbc/with-db-transaction clojure.core/with-open}}
#2020-03-0915:14Sasho@borkdude I can confirm your suggestion worked! Thank you.#2020-03-0915:14Sashothanks3#2020-03-0915:15borkdude:thumbsup:#2020-03-0918:31borkdudeCan someone remember that Clojure-Kit was suggest here by someone who made it work with clj-kondo?#2020-03-0919:10seriogaHi @borkdude Should not clj-kondo warn about if-let with single branch?#2020-03-0919:17seriogaFor this code with reader conditionals clj-kondo warns about “namespace rum.core is required but never used” (which is actually used in line 21). How should I lint code with reader conditionals?#2020-03-0919:18borkdude@serioga If the library is only used in clj or cljs you should put the require in a reader conditional#2020-03-0919:19seriogahm, this is not ergonomic...#2020-03-0919:21borkdudethat's your opinion 😉#2020-03-0919:21borkdudeabout if-let: I think an issue is warranted for that#2020-03-0919:25seriogafor single require reader conditional should be around (:require) 😞#2020-03-0919:26borkdude@serioga because (:require) isn't valid? yeah, that's how it is. clj-kondo lints a .cljc file twice: once for .clj and once for .cljs#2020-03-0919:27seriogaDoes it mean we should create an issue? https://clojurians.slack.com/archives/CHY97NXE2/p1583781706101500#2020-03-0919:28borkdudeluckily you can have multiple :require clauses, so it's not that much of an issue.#2020-03-0919:28borkdudeyes, it would be good to add an issue for that and it's pretty easy to fix. I'll make sure it gets into the next release#2020-03-0919:28serioga«luckily you can have multiple :require clauses» wow, interesting#2020-03-0919:32seriogahttps://github.com/borkdude/clj-kondo/issues/791#2020-03-0919:32borkdudethanks a lot.#2020-03-0919:33serioga«luckily you can have multiple :require clauses» the namespace order is tested independently in every :require?#2020-03-0919:34borkdudedo you mean by clj-kondo?#2020-03-0919:35serioga«do you mean by clj-kondo?» yes#2020-03-0919:35borkdudeI'm not entirely sure#2020-03-0919:36seriogaok, I'll test#2020-03-0919:36borkdude@serioga what you can also do: #?(:cljs [rum.core :as rum] :clj [rum.core]). clj-kondo will ignore namespaces that do not have an alias or referred vars#2020-03-0919:37seriogaI'm thinking about what to do with code like
(:require
    ; systems
    [app.app-system.service.app-config]
    [app.app-system.service.hikari-data-source]
    [app.app-system.service.immutant-web]
    [app.app-system.service.mount]
    [app.app-system.service.webapp-http-handler]
    [app.app-system.task.database-migration]
    ; imports
    [app.app-system.impl :as impl]
    [app.lib.util.integrant :as ig-util]
    [integrant.core :as ig])
#2020-03-0919:38borkdudeah yeah, maybe it works if you split them into multiple requires, I'm not sure#2020-03-0919:38borkdudeI'm assuming you are asking this because of the unsorted-required-namespaces linter#2020-03-0919:38seriogaIt works! Cool.#2020-03-0919:39serioga«I'm assuming you are asking this because of the unsorted-required-namespaces linter» exactly#2020-03-0919:39seriogaMultiple requires is a really nice hint.#2020-03-0919:40borkdudeoh maybe this could be documented and captured inside a unit test so we can keep this behavior as it is#2020-03-0919:40borkdudeif you want to do this, it might be an easy and nice PR#2020-03-0919:41borkdudeelse, posting an issue to remind me is also fine#2020-03-0919:42seriogaok, on it#2020-03-0919:48seriogawith multiple requires everything become clear
(ns app.lib.react.mount
  (:require
    [app.lib.react.component :as react-component]
    [app.lib.util.transit :as transit])
  #?(:clj
     (:require
       [clojure.string :as str])
     :cljs
     (:require
       [rum.core :as rum])))
so every format has its own section which is easy to maintain. https://clojurians.slack.com/archives/CHY97NXE2/p1583782598108900
#2020-03-0919:49borkdudecool.#2020-03-0920:09serioga@borkdude did you think about checking line length for documentation strings?#2020-03-0920:10borkdudeI'm not aware of any conventions around that. Is that important?#2020-03-0920:27seriogaI also not aware, but: • Cursive has option “Docstring fill width” with default value 80 • Cursive shows function documentation “as is” and long lines are not easy to read because of horizontal scroll So I thought maybe there a rule expected to keep lines in width 🙂#2020-03-0920:29seriogaAt least in clojure.core docstrings are fine#2020-03-0920:32seriogathis documentation format also shows docstrings as preformatted https://clojure.github.io/clojure/clojure.core-api.html#2020-03-0920:32borkdudeI'm hesitating to include this in clj-kondo because in general clj-kondo isn't concerned with formatting. it strips away all whitespace for example before it analyzes any code.#2020-03-0920:32borkdudemaybe it can be a feature of a clojure formatter tool#2020-03-0920:33serioga«it strips away all whitespace for example before it analyzes any code.» but not from docstrings I guess#2020-03-0920:33borkdudethat's true, but doesn't it also matter how far the string is indented itself?#2020-03-0920:33borkdudehmm, clj-kondo knows how far the string is indented btw. it has location metadata#2020-03-0920:33seriogaI mean linter can produce warning if docstring lines exceed specific width#2020-03-0920:34borkdudeyeah, I guess it could. make an issue and then we can think about it some more: what the warning and config should look like.#2020-03-0920:34serioga«doesn't it also matter how far the string is indented itself?» leading spaces are stripped as I know#2020-03-0920:35borkdudeplease provide some concrete examples in the issue#2020-03-0921:22dominicmDocstring width is fine until someone needs to paste a link in and tell the CI to go away for this one function.#2020-03-0921:53borkdude@dominicm If you have useful feedback on that issue, you can post it here: https://github.com/borkdude/clj-kondo/issues/793#2020-03-1000:17sogaiu(i line-break my urls using backslashes -- breaks links but keeps my code sane) 😛#2020-03-1007:38ikitommiis there a way to find out unused public vars?#2020-03-1007:50borkdude@ikitommi https://github.com/borkdude/carve#2020-03-1011:03dharriganCarve is pretty darn good 🙂#2020-03-1012:09borkdudeMaybe the #kaocha channel?#2020-03-1012:14dominicmToo many Ks, sorry :)#2020-03-1018:31seriogaclj-kondo warns here:
src\app\lib\vk\java_sdk\core.clj:10:47: warning: Unused import GetResponse
src\app\lib\vk\java_sdk\core.clj:12:35: warning: Unused import DomainResolved
but imports are used in type hints. @borkdude is it a bug or I missed something?
#2020-03-1018:33borkdudeseems like a false positive when using type hints in ->. welcome to post a repro with a minimal example in an issue#2020-03-1018:34seriogaok#2020-03-1020:17didibus@serioga I do always forget the right place to type hints, but if I remember correctly, you have your return type hints in the wrong place#2020-03-1020:17didibus
(defn ^:private ^ServiceActor conn-service-actor
  "Service actor from connection."
  [{:keys [::app-id
           ::app-service-token]}]
  (ServiceActor. app-id app-service-token))
#2020-03-1020:17didibusYou want ^ServiceActor hint to be on the arg vector, not the var#2020-03-1020:18didibusLike so:
(defn ^:private conn-service-actor
  "Service actor from connection."
  ^ServiceActor [{:keys [::app-id
           ::app-service-token]}]
  (ServiceActor. app-id app-service-token))
#2020-03-1020:18seriogaMaybe But I've put type hints to get rid of warning from Cursive and reflection warning 🙂#2020-03-1020:19didibusYa, but those probably do nothing#2020-03-1020:20didibusSo whatever got rid of your warnings it's not that#2020-03-1020:21seriogaI'll have a look with macroexpand#2020-03-1020:21didibusSee the doc https://clojure.org/reference/java_interop#2020-03-1020:21didibus> For function return values, the type hint can be placed before the arguments vector#2020-03-1020:22didibusI actually think clj-kondo should warn against that 😝#2020-03-1020:23didibusWhen you type hint where you did, you're type hinting the Var, but the Var holds a Fn, so its correct type is Fn, not ServiceActor#2020-03-1020:23seriogaIn the code above the problem is with result from .execute which has different types#2020-03-1020:25serioga@didibus are we talking about this code fragment?
(try
    (-> vk-api-client
        (.friends)
        (.get (conn-service-actor conn))
        (.userId (Integer/parseInt user-id))
        ^GetResponse (.execute)
        (.getItems)
        (->> (mapv str)))
    (catch ApiAccessException _
      (private-profile-friends))
    (catch ApiPrivateProfileException _
      (private-profile-friends)))
#2020-03-1020:25didibusI'm talking about:
(defn ^:private ^ServiceActor conn-service-actor
  "Service actor from connection."
  [{:keys [::app-id
           ::app-service-token]}]
  (ServiceActor. app-id app-service-token))
#2020-03-1020:26seriogathere is not warning about this https://clojurians.slack.com/archives/CHY97NXE2/p1583871935143100#2020-03-1020:26seriogathe warnings are about type hints in -> (2 places)#2020-03-1020:29didibusI just mean, in your function signature, I think the correct place to type hint the return value is the args vector#2020-03-1020:30serioga“I think the correct place to type hint the return value is the args vector” Agree I also think those hints are useless But I did not know this when wrote that code 🙂#2020-03-1020:31seriogaMaybe yet another case for clj-kondo to check and warn :-)#2020-03-1020:32serioga@borkdude what do you think? 😉 https://clojurians.slack.com/archives/CHY97NXE2/p1583872276147100#2020-03-1021:07borkdudeShall we focus on the first issue first (type hints in threading macros do prevent from unused import warnings). I haven't seen a Github issue for that yet 😉#2020-03-1021:09tanzoniteblack@borkdude https://github.com/borkdude/clj-kondo/issues/795 new (I think) false positive#2020-03-1021:10borkdude@serioga I think this is a minimal repro for your issue:
$ clj-kondo --lint - <<< '(ns foo (:import [foo Bar])) (defn foo [x] x) (defn bar [x] (-> x ^Bar (foo)))'
<stdin>:1:23: warning: Unused import Bar
linting took 11ms, errors: 0, warnings: 1
#2020-03-1021:10borkdude@tanzoniteblack Thanks, duplicate of #787#2020-03-1021:11tanzoniteblackI saw that one and wasn't clear they were duplicates of each other or not#2020-03-1021:11tanzoniteblackseemed like the same error, but probably due to different reasons#2020-03-1021:12borkdude@serioga Filed your issue here now: https://github.com/borkdude/clj-kondo/issues/796#2020-03-1021:12borkdude@tanzoniteblack I might have closed it prematurely. I'll take another look.#2020-03-1021:13borkdudere-opened it. I'll have a look at it before the next release#2020-03-1022:50borkdude@serioga @tanzoniteblack issues are solved on master now#2020-03-1101:23didibusSo, after talking to Alex Miller and Andy Fingerhut, it looks like putting return value type hints on the argvector and the var both work. But, the argvector should be favored in all cases.#2020-03-1101:24didibusThe argvector allows you to hint multi-arities which return different types. And it allows you to hint primitives.#2020-03-1101:25didibusThe var type hint can type hint multiple arities which return the same type all at ounce. And seems more intuitive to more people for some reason.#2020-03-1101:27didibusSo I don't know. I'm thinking a warning that recommends to type hint on the arg-vector instead of the var would be nice. But, in theory both are valid. So maybe make it an optional checker? I wouldn't mind either way. Personally, I would like it to be a default warn.#2020-03-1101:28didibusAlso, if you put it on both the var and the argvector, the argvector takes precedence.#2020-03-1101:30didibus
(defn ^String foo
  []
  "bar")
I'd make the above warn that type hints are recommended to be on argvector instead. And maybe this:
(defn ^String foo
  ^String []
  "bar")
Be a warn that there are two type hints defined for the same function.
#2020-03-1101:32didibusWhere as this would not warn:
(defn foo
  ^String []
  "bar")
or
(defn foo
  (^String []
  "bar"))
#2020-03-1101:49didibusThoughts?#2020-03-1107:19seriogaWell, I remember cases when the hint before var did not work. But unfortunately I cannot reproduce it in simple test case.#2020-03-1107:21seriogaAlso contract for defn from “The Essential Reference” does not mention ret-typehint before name at all.#2020-03-1107:27seriogaIn my file above the type hints before name also work#2020-03-1110:09borkdude@didibus Might be good to extract all this information into an issue on Github#2020-03-1110:39TwanHi! I was wondering if there exists a proper solution to this behavior:
(ns example
  (:require
   [hiccup.form :refer :all]))

(defn something []
  (form-to [:post "/somewhere"]))
Results into:
./example.clj
  :kondo/refer-all
    3:24 use alias or :refer
The refer list is however empty. Is this a bug, or should I add a lint-as here?
#2020-03-1110:41TwanRan with:
clj-kondo --lint ./example.clj --config '{:lint-as {hiccup.form/form-to clj-kondo.lint-as/def-catch-all}}'
./example.clj:3:24: warning: use alias or :refer
#2020-03-1110:41borkdude@twan clj-kondo will only list the referred vars if it knows about the required namespace. so if you will lint hiccup.form as well, it will do this.#2020-03-1111:32TwanYou mean like
(ns example
  (:require
   [hiccup.core]
   [hiccup.def]
   [hiccup.form :refer :all]))

(defn something []
  (form-to [:post "/somewhere"]))
?
#2020-03-1111:33TwanThat doesn't seem to make any difference#2020-03-1112:25borkdudeNo. Lint the source of hiccup. How else is clj-kondo supposed to know what is inside that namespace?#2020-03-1113:02borkdudeYou can do so by executing clj-kondo --lint $(lein classpath) in your project if you have a .clj-kondo directory in $PROJECT_ROOT#2020-03-1110:42borkdudeI don't see how this relates to :lint-as#2020-03-1110:43borkdudeThe problem here is that clj-kondo recommends not to use :refer :all but wants you to use :refer [form-to].#2020-03-1111:33TwanYes, I understand that clj-kondo wants me to do that, but it suggestion is empty (whereas it usually is filled with everything referred to)#2020-03-1213:36serioga@borkdude The :missing-docstring linter warns on deftype declarations like (deftype Foo [x]) . Is it intended behavior?#2020-03-1213:39borkdudeThat's probably a false positive. Issue welcome.#2020-03-1213:39borkdudeSame for deftest I see.
(ns foo
  {:clj-kondo/config {:linters {:missing-docstring {:level :warning}}}}
  (:require [clojure.test :as t]))

(deftype Foo [x])

(t/deftest foo)
#2020-03-1213:40seriogayes, deftest too single issue for both?#2020-03-1213:40borkdudeyeah#2020-03-1213:40borkdudejust paste that code into the issue#2020-03-1213:41borkdudein carve we ignore vars that are created by deftype / deftest, etc like this: https://github.com/borkdude/carve/blob/0e2a6014e684b2f2cea9e95e44d7bab215ba904f/src/carve/impl.clj#L108-L118#2020-03-1213:41borkdudeprobably the same applies to this linter#2020-03-1213:43serioga800! https://github.com/borkdude/clj-kondo/issues/800#2020-03-1213:43seriogathank you#2020-03-1213:44seriogabut it's possible to add docstring in both cases!#2020-03-1213:44borkdudeit is?#2020-03-1213:45serioga
(deftest ^{:doc "Docstring"} my-test)
#2020-03-1213:46borkdudehmm#2020-03-1213:46seriogabut for defrecord it useless.#2020-03-1213:47borkdudeit's not very common I think to write docstrings for tests#2020-03-1213:47borkdudepeople usually use testing#2020-03-1213:47seriogabut anyway deftest has no syntax for docstring#2020-03-1213:47borkdudeyeah, I think we just are going to ignore deftest and deftype for missing docstrings#2020-03-1213:47serioga«it's not very common I think to write docstrings for tests» I guess very uncommon#2020-03-1214:12serioga@borkdude hm, I cannot disable :unresolved-namespace linter for specific namespaces?#2020-03-1214:12borkdudewhy would you want to do that?#2020-03-1214:14seriogaI use criterium-core in comment criterium dependency is in profiles.clj I don't want import it in the file#2020-03-1214:15seriogawell, the (require '[criterium.core]) before “fixes” this issue...#2020-03-1214:29borkdudeyeah, that's the way to do it.#2020-03-1215:06seriogaShould not we lint for missing docstring for namespaces as well?#2020-03-1215:15borkdudecan do. I would say as an option to the existing linter.#2020-03-1215:16borkdudeor would you say, just enable it always for that linter?#2020-03-1215:18seriogathe option is more flexible I guess.#2020-03-1215:19borkdudeor maybe enable it by default but people can turn it off?#2020-03-1215:19borkdude{:missing-docstring {:level :warning :namespace-declaration false}?#2020-03-1215:21seriogaI don't have enough experience to say what is better Probably library and application developers have different expectations for default settings#2020-03-1215:22borkdudeI'll think about it some more. Welcome to post an issue about this.#2020-03-1215:22seriogaMaybe it would be useful to have an option like {:profile :lib}, and defaults change accordingly#2020-03-1215:22serioga@borkdude about namespace docstrings? https://clojurians.slack.com/archives/CHY97NXE2/p1584026520189500#2020-03-1215:30seriogaah, another topic was introduced later, OK#2020-03-1215:30seriogaI'll create issue#2020-03-1215:34seriogahttps://github.com/borkdude/clj-kondo/issues/801#2020-03-1215:35seriogaas another topic I mean https://clojurians.slack.com/archives/CHY97NXE2/p1584026536189900#2020-03-1215:38borkdudeif people need different settings for a lib, they can just change their config accordingly#2020-03-1215:38borkdudethere isn't going to be one default that satisfies everyone#2020-03-1215:39seriogapeople don't care but idea is to provide a guide for best practices for corresponding context#2020-03-1215:40seriogaat least on documentation level, as examples#2020-03-1215:41seriogafor example "missing docstring" is disabled by default. but it is no-go for libraries 🙂#2020-03-1215:41borkdudedepends#2020-03-1215:42seriogato easily apply https://clojure.org/community/contrib_howto#_coding_guidelines#2020-03-1219:55seriogaagain about rum macros.
(defcs name doc-string? (< mixins+)? [ state-arg params* ] render-body+)
when I define component like
(rum/defcs hello-world
  "Example react component."
  [state name]
  "foo")
then :missing-docstring linter still complains about missing docstring. @borkdude should I file an issue?
#2020-03-1219:56borkdudewhat are you linting rum as?#2020-03-1219:56borkdudewhat is your config?#2020-03-1220:01serioga
:lint-as {app.database.hugsql/declare-fn clojure.core/declare
           mount.core/defstate clojure.core/def
           mount.tools.macrovich/deftime clojure.core/do
           rum.core/defc clj-kondo.lint-as/def-catch-all
           rum.core/defcs clj-kondo.lint-as/def-catch-all
           rum.core/defcc clj-kondo.lint-as/def-catch-all}
#2020-03-1220:03seriogaah, without lint-as there is no message about docstring#2020-03-1220:03borkdudethat seems like a false positive then. you can append it to the existing issue.#2020-03-1220:04borkdudeincluding your config#2020-03-1220:04seriogahm, without lint-as it does not detect missing docstring...#2020-03-1220:05borkdudewithout lint-as it doesn't know what this macro is, so it also doesn't know it should have a docstring#2020-03-1514:39Marc O'MorainI just got my first error like this in a CI build:
test/circle/db/test_mongo_metrics.clj:1:1: error: Found an opening ( with no matching )
test/circle/db/test_mongo_metrics.clj:248:1: error: Expected a ) to match ( from line 1
#2020-03-1608:43eskosThinking out loud, could something like this be caused by BOM?#2020-03-1614:25borkdudeMore likely a typo.#2020-03-1810:33Marc O'MorainIt was fun - kondo found an unused :import - it was the only import in the ns form, so i removed the whole :import form. #2020-03-1810:33Marc O'MorainBut I accidentally removed the trailing ) which left the ns form open (no closing paren)#2020-03-1810:34Marc O'MorainSo the col 1 line 1 refers to the opening paren of the ns form. #2020-03-1615:27helios
(when-let [[_ map-decl map-path] (re-find #"(sourceMappingURL=(.*))\s*$" contents)]
    (let [map-path (str/replace map-path "$" "\\$")]
      (when-let [[new-map-path _] (get full-sha-map [(str/replace old-rel #"(?<=/)[^/]*$" map-path)
                                                 (str/replace old-full #"(?<=/)[^/]*$" map-path)])]
I'm getting a clj-kondo error Regex match arg requires string or function replacement arg. for both lines. Is it a bug? It's not clear to me what's wrong with the regex
#2020-03-1615:28borkdudeit's a bug. see the next-release column: https://github.com/borkdude/clj-kondo/projects/1#2020-03-1615:31borkdudeI hope to do a release on Friday, since it's clj-kondo's birthday then 🙂 (well, the first commit was on March 20th)#2020-03-1615:40heliosNice 😄 party @ this channel? 🎂 parrot#2020-03-1615:41borkdude🙂 you might want to lint with clj-kondo master to see if it fixes your issue#2020-03-1615:42heliosyes i've done it already. Props to deps.edn 😄#2020-03-1714:34danihello! I’m using clj-kondo in vscode via Calva and it doesn’t seem to be picking up the config.edn file inside .clj-kondo in the root of my project, no matter what I put there, the linting I get is always the same, can anyone help me troubleshoot what I’m doing wrong?#2020-03-1714:37borkdude@danimartinprieto clj-kondo looks from the current working directory upwards. VSCode set the current working directory to the workspace or directory that you are editing. If you are editing files outside your workspace, then clj-kondo won't be able to find the config.#2020-03-1714:41danimmm, it turns out vscode had opened as a workspace the parent folder of my project, I’ve closed it and open with vscode exactly the root of my project and now it works#2020-03-1714:41danithank you very much!#2020-03-1714:41borkdude:thumbsup:#2020-03-1714:43daniI have a follow up question… I have a macro that does this (it’s not important what it does, actually)
(defmacro defstyles [sym styles]
  "Takes a clojure map an creates a react-native StyleSheet from it without runtime clj->js conversion"
  `(let [s# (.create (.-StyleSheet (js/require "react-native")) ~(make-styles styles))]
     (defn ~sym [k#]
       (goog.object/get s# (name k#)))))
and every time I use it, it says the symbol it defines is unresolved… I’ve tried excluding that macro in the config file but it doesn’t work
:unresolved-symbol {:exclude [(my.macro.namespace/defstyles)]}
#2020-03-1714:44daniI’m not sure I’m doing it properly#2020-03-1714:52danithe unresolved symbol is not the macro itself, but what I define with it, so in this example: (defstyles styles …) styles is marked as unresolved and that’s what I want to avoid adding the exclude#2020-03-1714:57daniI’ve solved it doing :lint-as {my.macro-namespace/defstyles clj-kondo.lint-as/def-catch-all} please let me know if there is a better way!#2020-03-1714:59borkdudemaybe linting as clojure.core/def also works#2020-03-1715:00danibut it’s preferred? I have to say I’m learning clojure so…#2020-03-1715:03daniit seems it also work :thumbsup:#2020-03-1715:07borkdudeit will give you more accurate results. catch-all is the last resort#2020-03-1715:07danimakes sense, and thank you for your help ❤️#2020-03-1715:08borkdudenp, enjoy! 🙂#2020-03-1715:08daniand for creating the linter, actually, lol#2020-03-1715:08dani(I just saw it)#2020-03-1810:37Marc O'MorainIs there a particular reason why clj-kondo cannot or should not evaluate macros? We have some macros that evaluate to a def ultimately, and I have to keep my config.edn up to date with the macros. If kondo could macroexpand-1 the macros, would probably solve 80% of these cases. #2020-03-1810:37Marc O'MorainI can think of several problems:#2020-03-1810:38Marc O'Morain• this would mean evaluating code from the project (no longer “static analysis”) • this could introduce more warnings (unused let bindings, etc)#2020-03-1810:41borkdudeGraal does not support clojure.core/eval.#2020-03-1810:42borkdudeHaving said that, sci, the Clojure interpreter I wrote, does work with Graal. I've been considering using that for this purpose.#2020-03-1810:43borkdudeBut I'm unsure in how many cases it would work out well.#2020-03-1810:43borkdudeMaybe people could deliver stand-in macros via the configuration that will be evaluated using sci.#2020-03-1812:24borkdudeOne of the challenges is to translate rewrite-clj nodes into sexprs, then transform them using the user-provided sci macro/fn, and then transform them back into rewrite-clj nodes. We can disable certain linters like redundant do / let etc, that's easy.#2020-03-1818:49snoeI'm not sure if you've looked at my static approach to macros in clojure-lsp @U04V15CAJ It's certainly not perfect but might help with ideas that stop short of eval. https://github.com/snoe/clojure-lsp/blob/3502e8e1234642543c3900f78d02477e253dc0d4/src/clojure_lsp/parser.clj#L760#2020-03-1818:52borkdude@U0BUV7XSA Is this something users can also bring in as config themselves?#2020-03-1818:53snoeyup#2020-03-1818:53borkdudedo you have docs around this?#2020-03-1818:53snoehttps://github.com/snoe/clojure-lsp#macro-defs probably some things missing still#2020-03-1818:54borkdudeI was considering a DSL like this at one point, so thanks for the pointer#2020-03-1818:57snoenp. there's also what cursive does which is a step back from my dsl. Cursive let's you say parse my-macro as def|defn|let|for and then he hardcodes those library macros that do not fall in the common buckets.#2020-03-1818:58borkdudethat's also possible using clj-kondo, it's called :lint-as.#2020-03-1818:58borkdudehttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md#lint-a-custom-macro-like-a-built-in-macro#2020-03-1819:00snoedoes a lint-as feed into the analysis part? I've been thinking I could build lsp on top of kondo after looking at your analysis.#2020-03-1819:01borkdudenot entirely sure#2020-03-1819:03borkdudeone other idea I had is to add more clj-kondo.lint-as/... macros. users can just look at the shape and then lint as that macro. but so far a lot of the custom macros can already be mapped to supported macros#2020-03-1819:03borkdudeand the def-catch-all macro can be used as a last resort#2020-03-1819:08borkdudesci could be used like so:
{:lint-as {'foo.core/deffoo "(fn [_ _ name & body] `(def ~name 
, then sci could apply that function to the expression which invokes the macro and this will then be linted as a regular def
#2020-03-1819:15borkdudethat would be the ultimate DSL if you ask me, just Clojure itself#2020-03-1814:19Marc O'MorainI don’t have time to reduce this case down, but I have an NPE in clj-kondo from this code:
(ns circle.http.api.v2.context
  (:import [circle.http.defapi :refer [defapi-with-auth]]))
#2020-03-1814:20Marc O'Morain
Mar 18, 2020 2:18:57 PM org.eclipse.lsp4j.jsonrpc.RemoteEndpoint notify
WARNING: Failed to send notification message.
java.lang.IndexOutOfBoundsException
	at clojure.lang.PersistentVector.arrayFor(PersistentVector.java:158)
	at clojure.lang.PersistentVector.nth(PersistentVector.java:162)
	at clojure.lang.RT.nth(RT.java:896)
	at clj_kondo.lsp_server.impl.server$finding__GT_Diagnostic.invokeStatic(server.clj:71)
	at clj_kondo.lsp_server.impl.server$lint_BANG_$fn__6246.invoke(server.clj:106)
	at clojure.core$map$fn__5866.invoke(core.clj:2753)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:51)
	at clojure.lang.RT.seq(RT.java:535)
	at clojure.lang.SeqIterator.hasNext(SeqIterator.java:38)
	at org.eclipse.lsp4j.jsonrpc.json.adapters.CollectionTypeAdapter.write(CollectionTypeAdapter.java:134)
	at org.eclipse.lsp4j.jsonrpc.json.adapters.CollectionTypeAdapter.write(CollectionTypeAdapter.java:40)
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243)
	at com.google.gson.Gson.toJson(Gson.java:669)
	at org.eclipse.lsp4j.jsonrpc.json.adapters.MessageTypeAdapter.write(MessageTypeAdapter.java:434)
	at org.eclipse.lsp4j.jsonrpc.json.adapters.MessageTypeAdapter.write(MessageTypeAdapter.java:55)
	at com.google.gson.Gson.toJson(Gson.java:669)
	at com.google.gson.Gson.toJson(Gson.java:648)
	at org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler.serialize(MessageJsonHandler.java:145)
	at org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler.serialize(MessageJsonHandler.java:140)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageConsumer.consume(StreamMessageConsumer.java:59)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.notify(RemoteEndpoint.java:126)
	at org.eclipse.lsp4j.jsonrpc.services.EndpointProxy.invoke(EndpointProxy.java:88)
	at com.sun.proxy.$Proxy7.publishDiagnostics(Unknown Source)
	at clj_kondo.lsp_server.impl.server$lint_BANG_.invokeStatic(server.clj:103)
	at clj_kondo.lsp_server.impl.server.LSPTextDocumentService.didChange(server.clj:121)
	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$null$0(GenericEndpoint.java:65)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.notify(GenericEndpoint.java:152)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleNotification(RemoteEndpoint.java:220)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:187)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:194)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:94)
	at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
#2020-03-1814:21Marc O'Morain(I had an :import where I should have written :require )#2020-03-1814:53borkdudeah so you did reduce it down?#2020-03-1814:57borkdudehttps://github.com/borkdude/clj-kondo/issues/810#2020-03-2010:08borkdude#2020-03-2310:01Marc O'Morainawesome 👏#2020-03-1915:03MitchI noticed after a discussion elsewhere today that kondo will lint if but does not seem to lint if-not. I think the linting rules would be the same, so this should be an easy change. I can submit a pull request this weekend if we want this#2020-03-1915:05borkdude@mitchell_clojure https://github.com/borkdude/clj-kondo/issues/791#2020-03-1915:07Mitchshould have checked there. I can try my hand at it. Is there a name you like for #{if if-let if-not ...}? branching-conditionals?#2020-03-1915:07borkdudethere is a giant case expression in analyzer.clj. it has one case like this:
if (analyze-if ctx expr)
if that's changed to (if if-not) then I think it works for if-not as well
#2020-03-1915:08borkdudethe other one is:
(if-let if-some when-let when-some when-first)
                  (analyze-conditional-let ctx resolved-as-clojure-var-name expr)
but analyze-conditional-let doesn't check for missing else branches. it can be easily added.
#2020-03-1915:10MitchNice, that is where I was looking. I'll be able to spend a little time on it on Saturday. Thanks for the awesome tool#2020-03-1915:10borkdude:thumbsup:#2020-03-2009:03oliyi've had a look through the github issues so apologies if this is a dupe, do you think (get-in x [:y]) should be a linting error (prefer (get x :y) instead?)#2020-03-2009:41borkdude@oliy I don't think we have an issue for that one yet. I don't think it should be an error, but a warning.#2020-03-2015:40oliyi raised #815 for this, thanks#2020-03-2010:36borkdudeclj-kondo 1st birthday release! exactly one year ago the first commit in the clj-kondo repo was made. https://github.com/borkdude/clj-kondo/releases/tag/v2020.03.20#2020-03-2011:17jaihindhreddyWow. I still remember you announcing it vividly. Time flies. It's fun to watch the state of Clojure tooling advance so fast right in front of my eyes!#2020-03-2011:26dharriganCongratulations! Arch package updated! 🙂#2020-03-2011:27dharrigan
❯ clj-kondo --version 
clj-kondo v2020.03.20
#2020-03-2204:49didibusTime flies, but clj-kondo and sci I think are the best thing to happen to Clojure's ecosystem after cider(and orchard)#2020-03-2208:40borkdudeThank you!#2020-03-2204:49didibusSo Happy Birthday to it!#2020-03-2216:55seriogadamn, CLJS analyser does not like multiple requires
Only one :require form is allowed per namespace definition at line 1 src\app\lib\react\mixin\data_table.cljc
#2020-03-2217:02borkdudehaha ok#2020-03-2217:07seriogaand this case is not warned as incorrectly ordered
(:require
    [app.lib.html.icon :as icon]
    [app.lib.react.component :as component]
    [app.lib.react.mixin.push-state :as push-state]
    [app.lib.react.mixin.static-args :as static-args]
    [app.lib.react.util :as react-util]
    [cuerdas.core :as cuerdas]
    [rum.core :as rum]
    #?(:cljs [app.lib.util.history :as history])
    #?(:cljs [xlsx]))
#2020-03-2217:08borkdudeexpected: requires in reader conditionals do not have a defined sort order, so they are ignored#2020-03-2217:10seriogaare not reader conditionals “expanded” to code?#2020-03-2217:12borkdude@serioga they are, but if you do clojure-sort-ns in emacs, all reader conditionals go on top for example. because editors have different ways of dealing with reader conditionals, I have disabled that linter for reader conditionals, because it's a source of conflict between the linter and editor tooling#2020-03-2217:29seriogahm, but in this case reader conditionals work for order analyser...
(:require
    [app.lib.react.component :as react-component]
    #
#2020-03-2313:45Mitchdoes the master branch currently pass all tests? it is failing on 2 tests and throwing 1 error on my machine#2020-03-2313:46borkdude@mitchell_clojure Yes. What tests are failing for you?#2020-03-2313:47borkdudeTry script/test. This will populate your .m2 cache with certain dependencies that are linted in the tests.#2020-03-2313:47borkdude
# populate mvn cache for extract tests
clojure -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.9.0"}}}' -Spath > /dev/null
clojure -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.10.1"}}}' -Spath > /dev/null
clojure -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.520"}}}' -Spath > /dev/null
#2020-03-2313:54Mitch
ERROR in (run!-test) (core.clj:4789)
file arguments jar file as string or file
expected: (= findings (:findings (clj-kondo/run! {:lint [(io/file (System/getProperty "user.home") ".m2" "repository" "org" "clojure" "spec.alpha" "0.2.187" "spec.a
lpha-0.2.187.jar")]})))                                                                                                                                            
  actual: java.lang.ClassCastException: class .File cannot be cast to class java.lang.CharSequence (.File and java.lang.CharSequence are in module jav
a.base of loader 'bootstrap')                                                                                                                                      
 at clojure.core$re_matcher.invokeStatic (core.clj:4789)
    clojure.core$re_find.invokeStatic (core.clj:4838)
    clojure.core$re_find.invoke (core.clj:4838)
    clj_kondo.impl.core$filter_findings$iter__8301__8305$fn__8306$fn__8307$fn__8310.invoke (core.clj:291)
.
.
.

FAIL in (extract-clojure-core-vars-test) (extract_var_info_test.clj:12)
expected: (contains? vars (quote future))
  actual: (not (contains? #{} future))

FAIL in (extract-clojure-core-vars-test) (extract_var_info_test.clj:13)
expected: (contains? vars (quote transduce))
  actual: (not (contains? #{} transduce))
#2020-03-2313:54Mitchlet me double check my environment#2020-03-2313:54borkdudeto be sure, run lein clean#2020-03-2313:55borkdudehow are you running your tests from the command line?#2020-03-2313:55borkdudeand which OS?#2020-03-2313:58Mitchrunning on linux, openjdk 11#2020-03-2313:58Mitchwith lein clean then ./script/test#2020-03-2313:59borkdudelet me try that on macOS#2020-03-2314:00borkdudejust to make sure, you are on master? and your HEAD = 45c615fc969ab616303283faf3d3c744b6e71ba2?#2020-03-2314:01borkdudeall tests passing here, both with clojure and lein#2020-03-2314:02borkdude@mitchell_clojure https://pastebin.com/7qp2T4w6#2020-03-2314:02Mitchyeah, on the bump version commit#2020-03-2314:03borkdudecan you do a clean checkout of the repo, just to make sure? delete the previous one#2020-03-2314:04borkdudeI can't repro your problem#2020-03-2314:05Mitchyeah sure, I'll have to work on it some more tonight, but I'll update you on if it is an issue that could be accounted for on the public docs or not#2020-03-2314:18Mitchto add some context, though, I think it may be something up with my dev environment because Cider has had trouble with namespace resolution for some classes like namespaced-map-node#2020-03-2314:20borkdudemaybe try only running the tests with clojure to exclude any lein profiles issues?#2020-03-2314:21borkdude
clojure -A:test
#2020-03-2314:35Mitchyeah I still get the errors on a completely clean copy of the repo#2020-03-2314:35Mitchhave to do work now but I will follow up on this#2020-03-2319:19ullrichHi, We’re using plenty of goog.global in our codebase and I’m trying to get it ignored by clj-kondo. I thought I’d use :unresolved-symbol for that but I’m getting a java.lang.IllegalArgumentException: no conversion to symbol. Here’s an example with version v2020.02.28 clj-kondo --config '{:linters {:unresolved-symbol {:exclude [(goog.global)]}}}' --lint - <<< "(def global goog.global)" Anything obvious I’m doing wrong here? Also is :unresolved-symbol the way to go for goog.global or is there a way that I could use to actually get it working? Thanks 🙇#2020-03-2319:22borkdude@ullrich.schaefer if goog.global is not a function, don't wrap it in parens:
$ clj-kondo --config '{:linters {:unresolved-symbol {:exclude [goog.global]}}}' --lint - <<< "(def global goog.global)"
linting took 7ms, errors: 0, warnings: 0
#2020-03-2319:23ullrichZoom. Thanks for the quick answer 🙏 Just work 🙂#2020-03-2319:23borkdudeis goog.global something that is always defined in CLJS? then I think clj-kondo should just ignore it for CLJS#2020-03-2319:23borkdudeI'll make an issue for that.#2020-03-2319:24ullrichI believe goog.global is always defined. But I might be missing something obvious (again 😉).#2020-03-2319:26borkdudehttps://github.com/borkdude/clj-kondo/issues/816#2020-03-2514:29ullrichI’ve got a followup question to this. Until #816 has been addressed we ant to use {:linters {:unresolved-symbol {:exclude [...]}}} config. Is there a way to specify that this exclusion only applies to CLJ or CLJS?#2020-03-2514:53borkdudeno, it's global for both langs#2020-03-2514:53borkdudebut like I said, you can also do:
(def x js/goog.global)
#2020-03-2514:54borkdudeand this will give a warning in CLJ#2020-03-2514:54ullrichThanks#2020-03-2514:54borkdudeunless goog.global is renamed by advanced compilation, caveat!#2020-03-2514:56borkdudeyou can also use reader conditionals to ensure you use the symbol only from CLJS#2020-03-2514:56borkdudethose are all the options I can think of#2020-03-2514:57ullrichThanks for the input#2020-03-2319:27ullrichThanks @borkdude Great work on clj-kondo ! It sparks joy every time ❤️#2020-03-2319:28borkdudeah, it seems (def x js/goog.global) also works (instead of a config). Glad you enjoy it.#2020-03-2619:17seancorfieldclj-kondo newbie. Just getting it set up. We have a git monorepo where there's a build folder and a clojure folder, and inside the latter are about thirty subprojects, each with their own deps.edn. Where should I put the .clj-kondo folder?#2020-03-2619:18borkdude@seancorfield if the namespaces aren't conflicting among those subrepos, you can just put the .clj-kondo one level higher#2020-03-2619:19borkdudeif they are conflicting, just create a .clj-kondo in each of them
#2020-03-2619:20seancorfieldAll unique. Could it go in the top-level of the repo? I'll have to see where my .joker file was.#2020-03-2619:20borkdudeyeah, it can go into the top-level. clj-kondo just walks up from your current working dir until it finds one#2020-03-2619:25seancorfieldWoohoo! Atom / linter-kondo is working! That was a nice, easy switch from Joker!#2020-03-2619:27borkdude@seancorfield as a heads up, if you're encountering macros that are not recognized by clj-kondo, you can do mostly two things: 1) lint them as existing supported macros - https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#lint-a-custom-macro-like-a-built-in-macro 2) configure the :unresolved-symbol linter to ignore all errors inside the macro call - https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-unresolved-symbols-from-being-reported#2020-03-2619:27borkdudethe second one looks similar to something that joker has#2020-03-2619:28seancorfieldGood to know. I had quite a few macros declared in my .joker file.#2020-03-2619:29borkdudethe first option is preferred, since you'll still get proper linting, the second option just exists to reduce false positives#2020-03-2619:32seancorfieldJust run it on the entire classpath -- wow! And it only took 30 seconds, producing about 1,000 errors and 2,000 warnings. Guess I'll be curating some .clj-kondo/config.edn files for a while (and adding those to some of my libraries too it seems).#2020-03-2619:35borkdude@seancorfield if you run it on your classpath, the arity information from your libraries is saved to your .clj-kondo directory as well, so you will get arity errors for those inside your editor as well#2020-03-2619:38seancorfieldYeah, I'll have to start working through all the errors/warnings coming from 3rd party libraries that we use...#2020-03-2619:39borkdude@seancorfield you can ignore those in reporting while still benefiting from analyzing them. https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#include-and-exclude-files-from-the-output#2020-03-2619:41seancorfieldI tend to have a fairly zero-tolerance approach to lint warnings so I'll probably work to fix everything I can over the next few weeks, adding macro configs as needed too.#2020-03-2619:42seancorfieldI saw there are two linters that are disabled by default -- those are going to get switched on (I hate non-alphabetical :require clauses! 🙂 )#2020-03-2619:43seancorfield:unsorted-required-namespaces {:level :error} 🙂#2020-03-2619:44borkdudehaha#2020-03-2619:55seancorfieldIt flags this as missing a docstring: (defonce sys nil) -- but defonce can't take a docstring, right?#2020-03-2619:58dominicmDoc meta works#2020-03-2619:58dominicmIt just doesn't have a positional argument for it#2020-03-2620:00borkdude@seancorfield that's probably a false positive. I've been fixing some of those recently also for deftest, etc#2020-03-2620:00borkdudethis was the fixing commit: https://github.com/borkdude/clj-kondo/commit/4d12b70ab7c562023224a4e94f40f3050dc47cca#2020-03-2620:01borkdudefeel free to post an issue for defonce, it will be fixed in the next release (or you can do so if you wish)#2020-03-2620:04borkdudethis suffices as a repro:
$ clj-kondo --lint - --config '{:linters {:missing-docstring {:level :warning}}}' <<< '(defonce x 1)'
<stdin>:1:1: warning: Missing docstring.
linting took 8ms, errors: 0, warnings: 1
#2020-03-2620:05borkdudehmm, like @dominicm says, you could do this:
$ clj-kondo --lint - --config '{:linters {:missing-docstring {:level :warning}}}' <<< '(defonce ^{:doc "foo"} x 1) '
linting took 9ms, errors: 0, warnings: 0
#2020-03-2620:16seancorfieldYeah, I just added ^{:doc "..."} to it. I wasn't sure that would work. I've seen defonce followed by an alter-meta call to add docstrings (ugh!) so literal metadata is better.#2020-03-2620:28dominicmI'm not sure if that's really a bug or not. Defonce is as much part of your public api as def#2020-03-2620:34borkdudeyeah, so maybe it's fine as it is#2020-03-2621:04seancorfieldIt already found a couple of out-of-order :require's in my own code. I feel ashamed.#2020-03-2621:05seancorfield(I expect to find them in other people's code but my OCD normally prevents them in my own...)#2020-03-2700:04seancorfieldBoth clojure.java.jdbc and next.jdbc have a "with transaction" style macro that has the form (with-transaction [sym expr opts] & body) -- sym is introduced by the macro, for the body (like binding or several other core macros) but if I tell kondo to :lint-as any of those macros, it then complains about opts since a binding form should be an even number of forms. Can anyone think of a core macro that has an optional extra expression in a binding like that?#2020-03-2700:10seancorfield(I know I can turn off :unresolved-symbol inside the macro but that's a bit brutal)#2020-03-2700:17seancorfieldAlso
(+ (byte 32) 1)
what is the justification for error: Expected: number, received: byte? A byte is a number.
#2020-03-2707:42jeroenvandijk\#2020-03-2708:19borkdude@seancorfield The type warning is a bug in clj-kondo. You can override it with:
$ clj-kondo --lint - --config '{:linters {:type-mismatch {:namespaces {clojure.core {byte {:arities {1 {:ret #{:byte :number}}}}}}}}}' <<< '(+ (byte 32) 1)'
linting took 15ms, errors: 0, warnings: 0
#2020-03-2708:19borkdudeI'll make an issue for it#2020-03-2709:30borkdude@mitchell_clojure The strange issue you had was related to populating the m2 cache for the tests. It should now be fixed when you run script/test with master.#2020-03-2711:50Mitchthanks for the followup. confirmed fixed. was it just the version mismatch?#2020-03-2711:52borkdudeyeah#2020-03-2711:52borkdudeI upgraded from 1.10.1 to 1.10.2-alpha1, so that was the issue#2020-03-2711:52borkdudethis version was not yet in your m2 cache probably#2020-03-2712:18Mitchcool makes sense to me. interesting that lein/clojure didn't populate .m2 when run with the clojure-1.10.2-alpha1 profile/alias. thanks again#2020-03-2709:30borkdude@seancorfield The type warning got fixed on master (https://github.com/borkdude/clj-kondo/issues/819)#2020-03-2709:32borkdudethe relevant bit: https://github.com/borkdude/clj-kondo/commit/c5b8b7850420f054bcacfe56b3bfcbc3dafe8da1#diff-6d8aa5ed918d9c02addd52e5c039fc29#2020-03-2716:26seancorfieldFor now I worked around this in my code, but once that drops in a release, I'll change it back.#2020-03-2716:33borkdudecool. you can also use this config in the meanwhile:
{:linters {:type-mismatch {:namespaces {clojure.core {byte {:arities {1 {:ret #{:byte :number}}}}}}}}}
#2020-03-2716:34borkdudewithout having to change your code that is#2020-03-2716:36seancorfieldI already changed the code 🙂#2020-03-2716:37borkdudenote that you can also introduce type checking for arbitrary other functions you're interested in, this way. it's not used a lot yet, because it's not "for free" I guess#2020-03-2716:42borkdudebut for overriding bugs like this it's also quite handy 🙂#2020-03-2716:53seancorfieldGood to know. I will say that I am already super-impressed with clj-kondo -- it's an amazing piece of work!#2020-03-2716:59borkdudethanks!#2020-03-2709:39borkdudeAs for a lint-as config for clojura.java.jdbc with-transaction: clojure.core/let doesn't work unfortunately because of the opts, but I think this would be good to support out of the box in clj-kondo. Made an issue for it: https://github.com/borkdude/clj-kondo/issues/821#2020-03-2721:58seancorfieldhttps://github.com/borkdude/clj-kondo/pull/823 adds support for three with-db-* macros in clojure.java.jdbc and also next.jdbc/with-transaction#2020-03-2722:00borkdudeExcellent. Reading now.#2020-03-2722:08borkdudeMade a few comments. Overall, very good!#2020-03-2722:10borkdudeThe way I usually test "findings" is to first call (prn (lint! "...")) and then paste that output back into the test file and test it with (assert-submaps the-output (lint! "..."))#2020-03-2722:10borkdudeI'll paste that in the issue.#2020-03-2722:36borkdudeMerged. Thanks a lot. Do you need a new binary with this included or did you figure out how to build it yourself?#2020-03-2800:05seancorfieldI will just wait until you make a new release.#2020-03-2800:05seancorfield(and, thank you again, for an excellent project and also for taking the time to provide feedback in the PR)#2020-03-2709:40borkdudeIt can take a while since there are plenty other enhancements to make. Until then you can use the :unresolved-symbol config. If you want to speed up things, you could even try to contribute 🙂#2020-03-2716:52seancorfieldI'm off work today (I often take Fridays off, so I can have a 3 day weekend) so maybe I'll take a look as part of my "OSS Friday" routine 🙂#2020-03-2716:52seancorfieldAny particular guidance for how you like PRs packaged up? Code style? Tests?#2020-03-2716:56borkdudeHere's a document that should give some guidance: https://github.com/borkdude/clj-kondo/blob/master/doc/dev.md#2020-03-2717:01seancorfieldYup. Already reading it and I've forked the repo 🙂#2020-03-2715:48seancorfield@borkdude thank you for the swift responses!#2020-03-2715:55borkdude@seancorfield no problem. fwiw I have this in the config of the app I'm now working on:
:lint-as {clojure.java.jdbc/with-db-transaction clojure.core/let
           schema.core/defschema clojure.core/def
           reagent.core/with-let clojure.core/let}
but we're not using any opts in with-db-transaction
#2020-03-2716:02borkdudeI guess I can remove the config for schema.core/defschema, that's already supported for a while#2020-03-2716:25seancorfieldYeah, both clojure.java.jdbc/with-db-transaction and next.jdbc/with-transaction are like when-let when you don't provide options (only one binding allowed, so not really like let). I've never been happy with the syntax tho', because of this not-quite-let style.#2020-03-2716:32borkdudewith-open also works I guess#2020-03-2716:53seancorfieldGood to know. I will say that I am already super-impressed with clj-kondo -- it's an amazing piece of work!#2020-03-2721:58seancorfieldhttps://github.com/borkdude/clj-kondo/pull/823 adds support for three with-db-* macros in clojure.java.jdbc and also next.jdbc/with-transaction#2020-03-2811:50borkdudebtw, it's also possible to run a SNAPSHOT version of clj-kondo with docker:
$ docker run -v $PWD/src:/code/src --rm borkdude/clj-kondo:2020.03.21-SNAPSHOT clj-kondo --lint /code/src

/code/src/babashka/impl/clojure/test.clj:303:4: warning: unused binding m
#2020-03-3009:49borkdudeIn Q2 I'll apply for Clojurists Together funding to do work on clj-kondo, babashka and the Small Clojure Interpreter. Today is the last day you can fill our their survey. The backlog: https://github.com/borkdude/clj-kondo/labels/clj-together https://github.com/borkdude/babashka/labels/clj-together https://github.com/borkdude/sci/labels/clj-together#2020-03-3010:18Jakob DurstbergerI hope this isn’t a silly question, but I didn’t quite understand this from their website. Is the idea that you apply and if you get chosen you get paid to work on these repos?#2020-03-3010:19borkdudeYou can apply for a project you will work on. Others can fill out surveys and suggest projects that they want to support. If your project is mentioned enough, they will consider it.#2020-03-3012:57sogaiuso...where is the survey? am i missing something obvious?#2020-03-3012:58borkdudeThe Survey is sent if you are donating to Clojurists Together.#2020-03-3012:58sogaiuah, i see. thanks for the clarification.#2020-03-3017:14seancorfieldAh, I went off looking for the survey too. I didn't realize it only went to donors.#2020-03-3017:49borkdudeAt least that's my assumption. I could be wrong?#2020-03-3017:52Jakob DurstbergerYeah as far as I understood you only get a vote as someone who pays#2020-03-3100:37danielcomptonYep only members get surveyed#2020-03-3113:17borkdudeCreated an open collective for those who prefer it over Github sponsors. https://opencollective.com/clj-kondo#2020-03-3113:40borkdudethanks @jeroenvandijk / adgoji for the generous contributions#2020-03-3113:41jeroenvandijkThank you!#2020-03-3119:51borkdudeAny feedback on this PR? https://github.com/borkdude/clj-kondo/pull/826 My thoughts: the name could be clearer. Maybe get-in-single-key? Also I'm not sure: should we turn on this linter by default? Also: could it be generalized to assoc-in, update-in?#2020-03-3120:02tanzoniteblackI never really thought of (get-in x [:k]) an anti-pattern, so I'd probably lean towards turning this linter off if it was turned on by default. But that's of course just my personal opinion, interested to hear what others think#2020-03-3120:40seancorfield@borkdude I would definitely turn this linter on, if it wasn't on by default (as long as it doesn't give false positives). It's fair to extend it to assoc-in but with update-in you need to bear in mind that we didn't have update until Clojure 1.7 so a lot of older code had to have update-in with [:k].#2020-03-3120:40seancorfieldPerhaps :single-key-in as the general name for the linter?#2020-03-3121:04borkdudeI'll post your comment in the issue#2020-03-3121:07seancorfieldSorry, wasn't sure whether you wanted the feedback here or in the PR.#2020-03-3121:13borkdudeeither is fine#2020-04-0107:30Jakob DurstbergerMorning, I’ve raised above mentioned PR. I don’t quite understand why (get-in (from-cache-1 nil :clj 'clojure.core) ['defn]) would be a false positive? Also now I am not sure if I should comment here or on the PR 😄#2020-04-0107:45borkdude@jakob.durstberger Sorry, that was a false false positive 🙂#2020-04-0107:46borkdude@jakob.durstberger As for the suggestion: use (:foo ...) or (get x :foo) instead: maybe we shouldn't be doing that, since that may be stretching it: there are often multiple ways to get something out of something#2020-04-0107:47Jakob DurstbergerYeah, I think it leads down a brittle path as we would also have to add suggestions for assoc-in and update-in.#2020-04-0107:48Jakob DurstbergerI am currently looking into adding those. About it being on or off by default. I have no strong opinions. Another option would be to make it :info instead of :warning#2020-04-0107:48borkdudeI'd say turn it off by default. Document it in config.md under optional linters.#2020-04-0108:03Jakob DurstbergerSounds good to me#2020-04-0109:10borkdude@jakob.durstberger Made 3 small remarks to the code.#2020-04-0109:14Jakob DurstbergerAwesome, thank you. I’ll address these later today#2020-04-0109:15borkdudeThanks!#2020-04-0109:17Jakob DurstbergerAnd I also just realised that I haven’t added the linter to the docs yet#2020-04-0110:50chadhsdoes anyone have tips for slingshot and it’s try+ macro? getting errors on unknown symbols#2020-04-0110:54borkdude@chadhs Have you tried https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-unresolved-symbols-from-being-reported ?#2020-04-0110:56borkdudeso something like {:linters {:unresolved-symbol {:exclude [(slingshot/try+)]}}}#2020-04-0210:32chadhs{:linters {:unresolved-symbol {:exclude [(slingshot.slingshot/try+)]}}} this did the trick 🙂#2020-04-0210:34borkdudecool#2020-04-0111:01chadhsi didn’t want to do that wholesale, but being able to target just one function is perfecto 👌#2020-04-0111:01chadhsthanks @borkdude (btw, watched your recent talk on clj-kondo; well done!)#2020-04-0112:06Jakob DurstbergerDo you have a link to that?#2020-04-0112:11borkdudehttps://www.youtube.com/watch?v=MB3vVREkI7s#2020-04-0115:17Jakob DurstbergerThank you#2020-04-0111:02borkdudethanks 🙂#2020-04-0122:18nateI noticed that there is a :exclude-destructured-keys-in-fn-args to tweak the behavior of :unused-bindings, would you be amenable to adding a :exclude-fn-args that would not report on fn args at all?#2020-04-0122:24borkdude@nate in that case you can just start your fn args with an underscore#2020-04-0122:26natethe underscores are not popular, unfortunately (among the others that also work on the codebase I'm hacking on)#2020-04-0122:29seancorfield_foo is idiomatic Clojure for "this is not used" so maybe an opportunity to "educate" the others? 🙂#2020-04-0122:31borkdude:thumbsup:#2020-04-0122:31nateI will try#2020-04-0122:33bfabryit's also idiomatic python and ruby#2020-04-0122:33bfabryso the education will be multi-use!#2020-04-0122:34bfabryI had to satisfy pylint for this just yesterday#2020-04-0213:24borkdude@nate You can slap your colleagues around the head with the Clojure style guide: https://guide.clojure.style/#underscore-for-unused-bindings#2020-04-0214:38nateHahaha. Thanks for the link. Unfortunately, they are remote from me, so I'll have to ask them to print out a copy and slap themselves. #2020-04-0122:27seancorfieldIf I configure
:lint-as {expectations.clojure.test/defexpect clojure.test/deftest}
I would not expect to get a "missing docstring" warning on (defexpect foo ...) because I don't get that warning on (deftest foo ...) -- am I misunderstanding how "alike" the :lint-as makes things?
#2020-04-0122:28natewas hoping to be able to configure clj-kondo to still help me with my unused let bindings, perhaps a :only-let modifier then#2020-04-0122:32nateok, thank you#2020-04-0122:32borkdude@seancorfield That could be an issue in the missing docstring linter.#2020-04-0122:34borkdude@seancorfield The test for deftest is done here: https://github.com/borkdude/clj-kondo/blob/0fd662f207c8a6dd59f9473c88c7978e0a4c8e03/src/clj_kondo/impl/namespace.clj#L154#2020-04-0122:35borkdudeFeel free to post an issue about it and I'll take a look at it later.#2020-04-0122:35borkdudeOff to bed now#2020-04-0122:35seancorfieldOh, so it doesn't respect :lint-as relationships at all... fair enough.#2020-04-0122:36borkdudeyeah, lint as is more or less "analyze it with the syntax of this other thing", but it's a bit ambigious if we should treat everything in the linting as that other thing maybe#2020-04-0122:39borkdudeI guess it makes sense in the context of the missing docstring linter to treat it as a test and skip the warning#2020-04-0122:48seancorfieldWhen I get time, I'll see if there are other "special cases" where this sort of thing might crop up. Perhaps some sort of generic "symbol should be treated like one of these (set of symbols)" machinery can be added that would make this sort of thing easier in future...#2020-04-0207:50borkdudeFixed#2020-04-0214:57seancorfieldThat is cheating! And it also means that any regular function with :test Metadata will not get checked for a doc string.#2020-04-0214:59borkduderight, that may not be optimal#2020-04-0214:59borkdudeI hadn't thought of the case that some people use :test metadata on their regular functions, but some do#2020-04-0215:00borkdudeI'll put the issue in progress again#2020-04-0215:03seancorfieldUsing with-test or simply adding :test metadata is more common than I thought -- it has cropped up in several discussions here around testing and REPL-driven development recently 😸 #2020-04-0215:03borkdudeit's still trivial to fix, I'll make sure to do it before the next release#2020-04-0216:08borkdudePushed another one#2020-04-0217:01seancorfieldNice! Thank you!#2020-04-0208:07didibusWas kind of curious, since Cursive does auto-complete without a running REPL, I think just from its static analysis of the source code. And clj-kondo does static analysis of the source code for linting, how likely is it for it to maybe be used for driving auto-completion as well?#2020-04-0208:08didibusLike, if it can tell that a symbol is used that wasn't defined, or that some function take 3 arguments and not the 2 it's currently called with, doesn't that meant it has the information of all defined functions, macros and vars and their arities?#2020-04-0208:10didibusIf so, if it could be queried for it, Cider and Calva et all might be able to ask it for the list of possible completions within some context and maybe also the list of arguments for displaying that as well as you type?#2020-04-0208:23sogaiui have written some code that uses clj-kondo as a library to produce index information for identifiers and output as tags / TAGS. i use this to do jump-to-definition like things in various editors. in emacs i think it's supposed to be possible to leverage the info for completion as well. the main downside atm is that the initial indexing takes a while. for more details, you might find the following to be of interest: https://github.com/borkdude/clj-kondo/tree/master/analysis#2020-04-0208:43borkdude@sogaiu @didibus I think the approach that sogaiu takes can be combined with some editor plugin which lints the currently edited file and combines that with the already linted data, so incremental. that would solve the speed problem.#2020-04-0220:46didibusHum, interesting, but ya, this analyses data does feel like you have everything you need to auto-complete var names, macros, fns, namespaces, show arities and show doc#2020-04-0220:46didibusAs well as add jump-to-definition#2020-04-0220:47borkdudeyou can see what sogaiu made with clj-kondo here: https://github.com/sogaiu/alc.index-defs#2020-04-0220:47didibusAnd it would seem, you could even use it for refactoring, since it shows uses of vars and namespaces#2020-04-0220:55didibuslooks like github is down#2020-04-0220:59borkdudeyep. there are currently 4 tools that I know of that build on the analysis export. carve by me: finds unused vars and automatically removes them alc-index by sogaiu two listed here: https://github.com/clojure/tools.deps.alpha/wiki/Tools (morpheus and another one, both visualize dependencies between vars/namespaces)#2020-04-0221:05borkdudelooks like it's back: https://github.com/borkdude/clj-kondo/issues/836#2020-04-0208:44borkdudeso yeah, you can build something like this on top of the analysis export#2020-04-0208:53sogaiui've been thinking about the incremental approach a bit recently and i took some measurements for just the clj-kondo execution part. for clojure.core, i typically get between 0.7 to 0.8 secs. some post-processing is likely necessary but i'm not sure yet how much that might end up being. in the mean time, i'm trying to see what i can squeeze out of tree-sitter-clojure -- though even if that ends up faster, it's not likely to be nearly as accurate as clj-kondo.#2020-04-0209:35borkdudeIn other news, Sublime Text 3 users can use the LSP server: https://github.com/borkdude/clj-kondo/issues/827#2020-04-0211:17chadhsdoes anyone have a recommendation on how to set clj-kondo up to run as a pre-commit hook? similar to using lint-staged and husky in your package.json for those familiar with node based project.#2020-04-0211:35borkdude@chadhs I quickly whipped this one up:
#!/bin/sh

# To enable this hook, rename this file to "pre-commit".

if git rev-parse --verify HEAD >/dev/null 2>&1
then
    against=HEAD
else
    # Initial commit: diff against an empty tree object
    against=$(git hash-object -t tree /dev/null)
fi

if !(git diff --cached --name-only --diff-filter=AM $against | grep -E '.clj[cs]?$' | xargs clj-kondo --lint)
then
    echo
    echo "Error: new clj-kondo errors found. Please fix them and retry the commit."
    exit 1
fi

exec git diff-index --check --cached $against --
#2020-04-0223:30didibusWhy not a babashka script 😉#2020-04-0514:50chadhsalways good to default to plain old /bin/sh unless you need a feature from bash.#2020-04-0515:27borkdudethe main reason is that I just copied this from existing scripts. another good reason is that bb isn't available on every system and introduces a new dependency#2020-04-0211:42borkdudethanks for the idea, I should have done this much earlier 😉#2020-04-0211:55chadhsoh wow, cool and thanks; i’ll check this out.#2020-04-0211:57chadhshaha no worries. i released v1 of a small project / product in dec, so now i’m spending some time on “tech debt” in the form of tooling, more testing, refactoring before i add features. that sparked “wow i should really try clj-kondo”#2020-04-0211:58borkdudeAny further suggestions for commit hooks: https://github.com/borkdude/clj-kondo/issues/835#2020-04-0212:01chadhsyou bet, i’m planning to do that tomorrow during the morning.#2020-04-0315:55celwellHello, I’m having trouble getting rid of a error: #'om.next/path is private. I added :private-call {:exclude [(om.next/path)]} to my linters config, but it didn’t help#2020-04-0316:04borkdudeyou don't need the parens around om.next/path#2020-04-0316:12celwellThanks, unfortunately I’m still receiving the error. This my entire config, the rest of it works well:
{;; example :lint-as
 :lint-as {;; om.next/defui clojure.core/defprotocol
           rum.core/defc clojure.core/defn}
 :linters
 {:unused-binding {:level :off
                   ;; :exclude-destructured-keys-in-fn-args true
                   }
  ;; :missing-docstring {:level :warning}
  :unused-namespace {:level :off}
  :unused-private-var {:level :off}
  :unresolved-symbol {:exclude [(om.next/defui)
                                (om.next/ui)
                                (om.next/factory)
                                (om.next/get-query)
                                (rum.core/defcs) ; would like to add support for this
                                render
                                goog.DEBUG]}
  :private-call {:exclude [om.next/path]}}}
#2020-04-0316:19borkdudeAh, sorry. I don't think we have a config for this linter#2020-04-0316:20borkdudeI was confused about unused-private-var#2020-04-0316:22celwellAh ok. Hmm… any way to completely ignore a certain function from all linting?#2020-04-0316:23borkdudeI'm afraid not, but you can refer to the private var with #'foo/bar to avoid this warning#2020-04-0316:24celwellinteresting thanks#2020-04-0316:26borkdudemaybe we should just document that in the config.md page. so you can do (def path #'om.next/path) and then use that#2020-04-0316:27borkdudethis works in JVM clojure as well#2020-04-0317:51bringeHi, I'm using clj-kondo in vs code, v 2020.3.20, and seeing this "unused binding" warning when the binding is used inside a syntax-quoted form. Is this a bug? I saw a couple of similar, but not exactly the same, issues on the repo that were closed.#2020-04-0317:51bringeI'll create a new issue, if desired#2020-04-0317:53borkdude@brandon.ringe you're not actually using the argument unless you put a tilde before the y: ~y#2020-04-0317:54bringeOhh I see 😅 . Thanks#2020-04-0323:18rymndhnghey folks, I'm a bit late to the clj-kondo game (it's pretty awesome!)... I'm curious to know if this has replaced eastwood and kibit, or do folks still use all of them?#2020-04-0323:44seancorfield@rymndhng For me, clj-kondo has replaced Joker that I used to run automatically from my editor as a linter. I only used eastwood occasionally and have only used kibit once or twice.#2020-04-0323:45rymndhngThanks for sharing @seanm. Something that clj-kondo really has going for me is the fast execution. On a project at work.. clj-kondo takes one second... and kibit/eastwood take minutes 🔥#2020-04-0323:46seancorfieldJoker is also very fast, which was why I was using it as a linter from my editor (linting as I type).#2020-04-0323:46seancorfield(and also why I rarely used Eastwood/Kibit)#2020-04-0323:47seancorfieldPlus, Borkdude is extremely responsive and helpful!#2020-04-0407:43borkdudethanks! 🙂#2020-04-0420:20didibusI use kibit and Eastwood but only on build#2020-04-0420:20didibusWhere I don't mind the time they take#2020-04-0420:21didibusBut clj-kondo is like bringing IDE level functionality to editors that didn't have it, so that's much nicer!#2020-04-0420:22didibusI still combine it with joker for linting in-editor, since there's still some mutually exclusive linters between them#2020-04-0420:24didibusI believe both Eastwood and Kibit use core.logic for their linting, which is cool, but core.logic isn't very fast it seems in general, and quite difficult to optimize for.#2020-04-0420:47seancorfieldWhat would make you think that @didibus? A quick look at the project.clj for those projects shows they don't.#2020-04-0420:48didibusHum... The Kibit readme says: kibit is a static code analyzer for Clojure, ClojureScript, cljx and other Clojure variants. It uses core.logic to search for patterns of code that could be rewritten with a more idiomatic function or macro. For example if kibit finds the code#2020-04-0420:48seancorfieldInteresting...#2020-04-0420:48didibusI might have extrapolated wrongly for Eastwood#2020-04-0420:49seancorfieldAh, I missed it https://github.com/jonase/kibit/blob/master/kibit/project.clj#L9 -- yup.#2020-04-0420:50seancorfieldNow I'll have to double-check I read the Eastwood project deps correctly! 🙂 Sorry...#2020-04-0423:27niveauverleihI am trying to install clj-kondo for use with spacemacs on an armv8 32 bit architecture. What works is lein clj-kondo --lint source. The pure executable yields errors, probably because it's built for amd64. Does flycheck-clj-kondo use the jar or the executable? How can I build the executable?#2020-04-0423:30sogaiui think an executable is used: https://github.com/borkdude/flycheck-clj-kondo/blob/master/flycheck-clj-kondo.el#L53_L56 also there is this bit from the README: > Before installing the Emacs package, make sure the clj-kondo is on your path. For installation instructions, see https://github.com/borkdude/clj-kondo. afaik, there are no arm builds -- but would be happy to be wrong about that 🙂#2020-04-0423:36niveauverleihThanks @sogaiu! So I'd better build it. I saw the source code was on github. I would be glad if someone could provide me with the command that I need to execute in order to build it.#2020-04-0423:37sogaiui typically use the compile script that lives in the script directory#2020-04-0423:37sogaiuthat script assumes you've got graalvm's native image (or at least GRAALVM_HOME pointed somewhere relevant) as well as leiningen#2020-04-0423:38sogaiui'm not sure if arm support exists for the jdk 8 based graalvm -- i think i read that there may be some for the jdk 11 based graalvm#2020-04-0423:42sogaiunot sure how helpful it might be, but found this: https://github.com/gluonhq/client-samples#2020-04-0507:06borkdude@nick.romer if the executable isn’t an option, you could also try the LSP server which uses a regular JVM#2020-04-0507:53niveauverleihThanks @sogaiu ! @borkdude I see you already asked the arm question to the graal team. So graal is currently not an option. I'll read up on the LSP server.#2020-04-0507:54borkdude@nick.romer Can you remind me where I asked this? if this was about cross-compilation, it doesn't necessarily mean ARM is not supported#2020-04-0507:54borkdudejust that you cannot cross compile#2020-04-0507:55borkdudeGraalVM offers downloads for mac arm64, linux arm64, but also aarch64 which I think is arm?#2020-04-0507:55borkdudeoh I see sogaiu mentioned that it might only be there for java11#2020-04-0507:55borkdudeanyway, yeah, LSP is a great fallback#2020-04-0507:56borkdude@nick.romer Are you using emacs? https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#lsp-server#2020-04-0508:15yuhanIs this a false positive? It looks like defining a custom def macro in a namespace (like spec does) doesn't overshadow the special form, but clj-kondo considers it to be the case
(ns foo)

(defmacro def
  [x y z]
  ,,,)

(def x 42) ;; -> foo/def is called with 2 args but expects 3
#2020-04-0508:28niveauverleih@borkdude here https://github.com/oracle/graal/issues/1329 yes I use spacemacs on termux-ubuntu on a Samsung A10 smartphone.#2020-04-0510:02borkdude@qythium Correct, that is a false positive. E.g. spec also defines def but a special form is always prioritized over var names: https://github.com/clojure/spec.alpha/blob/5a4834eeb2967b2eca382efe0afcb3f590bdb3c2/src/main/clojure/clojure/spec/alpha.clj#L349#2020-04-0510:04borkdude@qythium This issue already mentions that problem: https://github.com/borkdude/clj-kondo/issues/639 I'll change the title so it will cover this issue more clearly.#2020-04-0510:19yuhanThanks! I wonder if it's idiomatic to actually do this or deserving of a warning, given the precedent in clojure.spec. After all it's not shadowing anything and can only be referred to in fully qualified form#2020-04-0510:21borkdude@qythium yeah. I think a warning would be appropriate (which you can then fine-tune using a config).#2020-04-0511:41orestisIs there any way to get the clj-kondo to exit with status 1 iff errors are present? Ie ignore warnings. I’m currently relying on parsing the output. #2020-04-0511:43borkdude@orestis does this answer your question? https://github.com/borkdude/clj-kondo#exit-codes#2020-04-0511:44orestisHm did that change recently? I remember looking at exit codes when I started. Still needs a small wrapper but better than parsing output. #2020-04-0511:45orestisThanks!#2020-04-0511:45borkdudeno, it's been there all along#2020-04-0511:45borkdudewell, pretty much since the beginning, maybe a few weeks in#2020-04-0512:02borkdudeclj-kondo v2020.04.05 - warn about conflicting alias - optional warn on usage of get-in, assoc-in etc. with single keys and other stuff! https://github.com/borkdude/clj-kondo/releases/tag/v2020.04.05#2020-04-0517:22seancorfield@borkdude Awesome new release -- thank you! With the with-(db-?)-transaction support, it found a couple of places where I accidentally did this
(jdbc/with-db-transaction [t-con db-spec]
    (jdbc/execute! db-spec [,,,]))
instead of this
(jdbc/with-db-transaction [t-con db-spec]
    (jdbc/execute! t-con [,,,]))
so that's a real bug in the code it found!
#2020-04-0517:43seriogaThat's exactly why I asked if you consider API with shadowing 🙂#2020-04-0517:46borkdude@U0HJNJWJH Did you ask something to the JDBC maintainers or clj-kondo? I don't follow#2020-04-0517:46seriogaIn my project I wrote a macros around your macros for shadowing.
(defmacro with-transaction
  "Helper for `jdbc/with-transaction` allowing specify connection
   symbol only once and shading non-transactable name."
  [spec & body]
  (let [spec (if (vector? spec)
               (into [(spec 0)] spec)
               [spec spec])]
    `(jdbc/with-transaction ~spec
       
#2020-04-0517:47serioga@borkdude I asked Sean about with-db-transaction in #sql#2020-04-0517:48borkdudeok#2020-04-0518:30seancorfieldI don't recall seeing that come up in #sql but I do remember you asking about (with-transaction con ,,,) as a shortcut for (with-transaction [con con] ,,,) and I said it wasn't a good idea to have two different syntaxes for a macro -- and why I think your with-transaction is a bad idea too.#2020-04-0518:31seancorfieldStuart Sierra talks about why that's an antipattern: https://stuartsierra.com/2015/06/10/clojure-donts-heisenparameter#2020-04-0518:32seancorfield(he's talking about functions but it applies equally to macros)#2020-04-0518:37serioga@U04V70XH6 My question was not about collection/not collection. My question was about making db-spec not available inside transaction because this name is replaced (shadowed) with t-con inside the block. In case like this even linter will not help (because t-con is already used):
(jdbc/with-db-transaction [t-con db-spec]
    (jdbc/execute! t-con [,,,])
    (jdbc/execute! db-spec [,,,]))
#2020-04-0518:41seriogaFound my original question in archive Did you consider next.jdbc API for with-transaction where sym shadows name of transactable ?
; Current API
(with-open [conn (jdbc/get-connection my-datasource)]
  (jdbc/with-transaction [tx conn]
    (jdbc/execute! tx ...))) ; what is allowed to do with `conn` here?

; Alternative - the lexical scope of `conn` is changed
(with-open [conn (jdbc/get-connection my-datasource)]
  (jdbc/with-transaction [conn]
    (jdbc/execute! conn ...))) ; outer `conn` not accessible here
#2020-04-0518:41seancorfield
(with-transaction [db-spec db-spec]
  (execute! db-spec ,,,))
is that what you're trying to achieve?
#2020-04-0518:43seancorfieldThis conversation should probably go to #sql at this point.#2020-04-0517:23seancorfieldAlso verified my (+ (byte c) i) code is no longer flagged.#2020-04-0517:23borkdudeNice, so db-spec was reported as unused?#2020-04-0517:23seancorfieldAnd the new :single-key-in linter flagged a bunch of stuff in our code too so "yay!" on that as well!#2020-04-0517:24seancorfieldIt reported t-con was an unused binding -- correctly -- which is a bug because the wrapped code should use the transaction not the original db spec.#2020-04-0517:24borkdudeAh right. Nice :-)#2020-04-0604:32jumarI haven't been watching clj-kondo for a while but it looks it's getting better and better all the time - great work! 🙂 I have a few questions regarding project setup • Do I still need to create .clj-kondo directory manually? could that be created automatically instead? (I guess I often forget to do this for a new project) • How often, in practice should I clj-kondo --lint "<classpath>" ? Should I re-run it after adding a new dependency? • Would it make sense to have a global ~/.clj-kondo/config.edn for default configuration shared by all projects? (I haven't found an equivalent to this option in https://github.com/borkdude/clj-kondo/blob/master/doc/config.md)#2020-04-0604:47seancorfield@jumar While that latter sounds appealing, it undermines repeatability -- if the only configuration is per-project, then that config can be checked into git with the rest of the project and anyone else working with the project gets the same clj-kondo config.#2020-04-0604:49jumarOh, that's right. I'm mostly interested in linting projects where others are not (yet) using clj-kondo. Or perhaps have really a default for every project (including personal projects) and then, perhaps later, provide specific configurations for team projects.#2020-04-0604:49seancorfieldI've started seeing .clj-kondo/config.edn in more and more projects lately so...#2020-04-0604:55jumarWould you mind sharing yours?#2020-04-0604:58seancorfield
{:linters
 {:consistent-alias
  {:aliases
   ;; straw man for some standardization:
   {clojure.string str,
    com.stuartsierra.component component,
    next.jdbc jdbc, next.jdbc.result-set rs, next.jdbc.sql sql,
    ring.util.response resp}}

  :missing-docstring {:level :warning}

  :single-key-in {:level :warning}

  :unsorted-required-namespaces {:level :error}}

 :lint-as
 {expectations.clojure.test/defexpect clojure.test/deftest}}
 ;; I'm not sure whether we want to skip (comment,,,) forms or not...
 ;; ...having it flag def for having no docstring is kind of annoying
 ;; but having it flag all sorts of other things in (comment,,,) is useful
 ;; :skip-comments true}
#2020-04-0604:59seancorfieldI've removed the World Singles specific stuff -- and this is just the start of what I expect to be in there over time...#2020-04-0605:04seancorfieldI haven't spent much time configuring it for Expectations so I'm still seeing a lot of warnings and errors in our test suite. I suspect that will require quite a bit of work since there are some... interesting... macros there that add some unusual syntax...#2020-04-0608:23seriogawarning: Missing docstring is back on deftype in yesterday release...#2020-04-0608:26seriogait was this issue https://github.com/borkdude/clj-kondo/issues/800#2020-04-0608:26seriogait was this issue https://github.com/borkdude/clj-kondo/issues/800#2020-04-0608:46borkdude@serioga Hm, that is a regression for fixing a problem seancorfield had.#2020-04-0608:46borkdudeI'll look at it, again. I see we didn't add a proper unit test for that case last time 😕.#2020-04-0609:33borkdude@jumar yes, yes and no (https://github.com/borkdude/clj-kondo/issues/736)#2020-04-0609:34jumarGreat, thanks! Do you know if there's a workaround when using it in an editor (Spacemacs)?#2020-04-0609:35borkdudeworkaround for what?#2020-04-0609:41borkdudeI'm not sure what you are referring to since you brought up three different questions#2020-04-0609:47jumarHaving global config and using --config#2020-04-0609:50borkdudeflycheck-clj-kondo accepts extra arguments you can pass to it. https://github.com/borkdude/flycheck-clj-kondo/blob/f652a8dc4cff01e78bba50b555bae7ba6115b552/flycheck-clj-kondo.el#L68 so if you call that function with "--config" "..." in your emacs setup, that will be given to clj-kondo.#2020-04-0609:52borkdudeI can't speak about spacemacs since I'm not using it, but this is just a regular elisp package which you should be able to call#2020-04-0615:23jumarThanks, that should work!#2020-04-0609:36borkdude@serioga Issue fixed (again) on master. If you want I can provide you with a link to a new binary, or you can build your own. Since I just released it's going to a few weeks until the next one I think.#2020-04-0609:38seriogaThank you. Release is not necessary, I can wait :-)#2020-04-0609:38seriogaThank you. Release is not necessary, I can wait :-)#2020-04-0616:46seancorfield@borkdude Some time this week I'm going to carve out a couple of hours to look more deeply at clj-kondo and Expectations (specifically the clojure.test-compatible version) and see what I can configure and what I need assistance with (or, perhaps, enhancements to clj-kondo for).#2020-04-0616:49seancorfieldPart of the issue is that Expectations has some syntactic constructs that seem hard to deal with, but I need to do deeper analysis to figure out exactly what action to take to get clj-kondo to be happy with them. The primary one I've seen but not yet spent time on is more-of which takes as its first argument a form which is essentially a destructuring: (more-of {:keys [a b c]} expected actual expected actual,,,)#2020-04-0616:50seancorfieldSo there's nothing in Clojure to "lint as" and I'd still like the body to be analyzed...#2020-04-0617:36borkdude@seancorfield When I read the notification on my phone I thought you were talking about https://github.com/borkdude/carve 🙂#2020-04-0617:38borkdudeYeah, weird macros are an ongoing problem. I've been playing around with the idea to let people provide a standin function in their config and let the Small Clojure Interpreter transform the expression using that function to something known, but that's something that won't land any time soon I think, if it ever will#2020-04-0617:38borkdudeso for now the best we have is :lint-as and :unresolved-symbol + :exclude#2020-04-0617:39borkdudeI hope in time that we have enough macro's that people can use lint-as for, but there's always exceptions#2020-04-0617:40seancorfieldIt certainly encourages people to think more carefully about the syntax of macros they add to libraries 🙂#2020-04-0617:42seancorfieldThe whole with*transaction thing in the JDBC libraries comes about purely because they are macros that introduce syntax that isn't really like anything else in Clojure (in their case a "binding" form that can have three expressions -- something I would change if I were to do-over).#2020-04-0617:43borkdudeif someone can provide support for expectations, maybe those can be transformed into deftest-like expressions. clj-kondo has support for detecting missing assertions which you would then also get. I'm not familiar with expectations myself. is it widely used?#2020-04-0617:45seancorfieldIt is not. There are two flavors: "classic" Expectations which uses unnamed tests and runs them all by default at JVM shutdown and therefore has all sorts of Expectations-specific tooling; and the new version which uses named tests so it can be clojure.test-compatible but still retain a lot of the compact syntax from the classic version.#2020-04-0617:46seancorfieldI maintain both so, worst case, I will end up submitting PRs to clj-kondo to add support for these things.#2020-04-0617:47seancorfieldIt's made somewhat more complex by the fact that really only defexpect and expect are macros -- the rest, while they also exist as macros, are just special symbols that expect knows about.#2020-04-0617:47borkdudehmm, those kind of macros are especially nasty to lint yes#2020-04-0617:47seancorfield(they exist as macros so it's easier to show docs for them and it might be easier to integrate into other tooling)#2020-04-0617:48borkdudemaybe you can write a third version of expectations that has the same syntax has deftest, or similar to other macros 😉#2020-04-0617:49seancorfieldI'll see what falls out of my work with clj-kondo and our test suite this week...#2020-04-0700:28seancorfieldAnalyzing more-of in Expectations is very, very close to analyze-as-> (just without the as-expr at the beginning). So far, everything else I've looked at with clj-kondo seems to analyze pretty much out of the box.#2020-04-0700:29seancorfieldfrom-each can be linted as clojure.core/for. more-> would need a custom analyzer as well (hmm, it would be very, very similar to cond-> except it doesn't have a start-expr).#2020-04-0617:50borkdudeok#2020-04-0712:37Marc O'MorainIn my projects, I get a lot of false positives for accessing private vars from tests. Is there a neat trick to change lint rules between src and test ?#2020-04-0712:40borkdude@marc-omorain The way to get around this is to use #'foo/bar instead of foo/bar#2020-04-0712:40borkdudeI bet this is CLJS?#2020-04-0712:42Marc O'MorainNope, is regular Clojure. Looking deeper, it comes from using bond/with-stub from https://github.com/circleci/bond#2020-04-0712:42borkdudehmm, in clojure you can't even do this, the compiler will throw#2020-04-0712:44Marc O'MorainThe #' trick might work, I’ll check.#2020-04-0712:46borkdudefwiw you can bind private vars in clojure: (binding [foo/*bar* 1] ...) even if foo/*bar* is private and clj-kondo knows about this, so linting as that one might work - although the syntax of your stubbing lib seems slightly different, so I'm not sure if that will work#2020-04-0712:48borkdude@marc-omorain Another solution is to turn off the private linter locally:
(ns foo)

(def ^:private x 1)
x

(ns bar
  {:clj-kondo/config {:linters {:private-call {:level :off}}}}
  (:require foo))

foo/x
#2020-04-0712:48borkdudethe linter is called :private-call which should be renamed to :private-var-usage or something in the future, but we will keep backwards compatibility#2020-04-0712:50borkdude(see https://github.com/borkdude/clj-kondo/issues/692)#2020-04-0712:53borkdudewould have been easier if the with-stub macro syntax was exactly the same as binding#2020-04-0712:56borkdudemaybe that can still be retrofitted without breaking the current contract#2020-04-0712:56borkdude^ @marc-omorain#2020-04-0712:57Marc O'MorainThanks 🙏 I’ll take a look at those options.#2020-04-0800:29sogaiui just had luck building and running clj-kondo for aarch64 🙂#2020-04-0800:29sogaiui'm off to try babashka#2020-04-0807:08borkdudeWow!#2020-04-0807:52eskosWhat would be the correct approach to make a custom linting rule which would disallow using :refer in ns requires? This is a sort of in-house rule we have to keep things legible, and would be nice to get clj-kondo to warn about those 🙂#2020-04-0807:54borkdudeyou always want to use aliases or fully qualified namespaces?#2020-04-0808:23eskosAlways :as something 🙂#2020-04-0808:25eskosOh and this also means no :refer-macros as well, if that wasn’t obvious yet…#2020-04-0808:52borkdude@suomi.esko We don't have any API to make custom linters, but since this kind of rule isn't specific to any one code base, I suggest we bake this into clj-kondo as an optional linter. we already have: :use {:level :warning}. we could make one for :refer as well.#2020-04-0809:38eskosI’d love that 🙂#2020-04-0809:40borkdudeok, could you post an issue?#2020-04-0809:58eskosThat I can! 😄 A moment.#2020-04-0813:54plinshello, Im running clj-kondo —lint . on a clojure project and Im getting this error
./src/y/x/goal/core.clj:3:37: warning: #'integrant.repl/clear is referred but never used
./src/y/x/goal/core.clj:3:43: warning: #'integrant.repl/go is referred but never used
./src/y/x/goal/core.clj:3:46: warning: #'integrant.repl/halt is referred but never used
./src/y/x/goal/core.clj:3:51: warning: #'integrant.repl/prep is referred but never used
./src/y/x/goal/core.clj:3:56: warning: #'integrant.repl/init is referred but never used
./src/y/x/goal/core.clj:3:61: warning: #'integrant.repl/reset is referred but never used
./src/y/x/goal/core.clj:3:67: warning: #'integrant.repl/reset-all is referred but never used
but there is no explicit reference to integrant whatsoever in the file, here is the require block (it says line 3 right?)
(ns dojo.y.x.core
  (:require [clojure.spec.alpha :as s]
            [y.x.common.spec :as cs]
            [y.x.onboarding.core :as onboarding]
            [y.x.settings.user :as user]
            [y.x.team.core :as team]
            [y.helper.math :as math]
            [y.helper.time :as time]
            [y.integration.db.core :as db]
            [y.integration.http.ff-gg :as asc]
            [taoensso.timbre :as log]))
#2020-04-0814:55borkdude@plins which version of clj-kondo are you using? and this is a public repo so I can reproduce the problem?#2020-04-0815:07plinsclj-kondo v2020.04.05#2020-04-0815:08plinsnot a public repo, Ill try to nail down the problem to a small reproducible version thanks 🙂#2020-04-0815:09borkdude@plins fwiw the filenames reported do not match the namespace form you posted#2020-04-0815:47plinsmy mistake, but I edited those in slack just to do not post private stuff sorry#2020-04-0815:47borkdudeok, I'm going to wait for the repro#2020-04-0908:32heliosCould this be a bug? https://nextjournal.com/helios/clj-kondo-md-repro There's something off with js interop and detecting whether we use or not a required ns#2020-04-0908:34helioscc @borkdude 🙂#2020-04-0908:49borkdudeis this related to shadow-cljs somehow?#2020-04-0908:50borkdudeI mean, using the alias as some value?#2020-04-0908:51borkdude
$ plk
ClojureScript 1.10.520
cljs.user=> (require '[clojure.set :as s])
nil
cljs.user=> s
            ^
WARNING: Use of undeclared Var cljs.user/s at line 1
nil
^ @helios Not sure if I understand your repro. Could you post some real working code using CLJS only?
#2020-04-0908:52helios@borkdude we don't use shadow-cljs. But this is just a snippet from our codebase#2020-04-0908:53borkdudewithout a repro I can understand, I can't say if this is a false positive or not.#2020-04-0908:54borkdudepretty cool that you did it with nextjournal though 😉#2020-04-0908:55helios
(ns foo
  (:require [markdown-it-texmath :as md-texmath]))
           
(use md-texmath)
will say that markdown-it-texmath is required but never used
#2020-04-0908:56borkdudewhat is use? I've never seen that in CLJS#2020-04-0908:56borkdudeif this is about requiring namespaces using use I'd say this is pretty weird code, especially in CLJS?#2020-04-0908:59helioshttps://github.com/clojure/clojurescript/blob/r1.10.597/src/main/clojure/cljs/core.cljc#L3019#2020-04-0908:59borkdudeif you could go through the trouble setting up a small CLJS project which has this code and I can run this using the clojure CLI, I'd be happy to take a further look#2020-04-0909:00heliosi don't think it should complain that md-textmath is not being used, technically#2020-04-0909:00heliosI don't know yet what it does in the context, i'll try to figure it out#2020-04-0909:01borkdude@helios I still don't understand why this code should work at all. Using use is very rare in CLJS, especially in a threaded expression#2020-04-0909:02heliosFor one second consider the second example. Why is that code not supposed to work?#2020-04-0909:03borkdudebecause use requires namespaces and md-texmath is an alias? normally you use aliases like (md-texmath/foobar) to refer to a function of a namespace#2020-04-0909:03borkdudeI'm not saying it doesn't do something, but I don't understand this construct#2020-04-0909:06borkdudeWhat I expect to see is something like:
(ns foo
  (:require [markdown-it-texmath :as md-texmath]))

(md-texmath/dude)
#2020-04-0909:07borkdudeI'll try with lumo#2020-04-0909:09borkdude@helios#2020-04-0909:12heliosOkay, i'll investigate a bit further to understand what the snipped with the threading is supposed to do and why it's not blowing up in our codebase#2020-04-0909:30Andreain the example above use in this case is an instance method of the return value of md not the clojure use, it’s threaded cljs style with the dot-dot ..#2020-04-0909:40borkdude@andrea712 Is it possible to create a small repro that I can run with e.g. lumo? I can npm install any lib and then run a script with lumo. Should be relatively easy to do#2020-04-0909:41borkdudeAnd then post this as an issue in the clj-kondo github repo#2020-04-0909:50Andreacan discuss it with @helios, I’m not an expert in the field but maybe we’d need to make lumo aware of some piece of cljs compiler options about :global-exports ? cc @kommen#2020-04-0909:50borkdude@andrea712 using pure CLJS is also fine, as long as I can run it to see what's happening#2020-04-0909:51borkdudeI just thought lumo would be less work, since you can just run a script, but a small repro repo using no downstream tooling might be better#2020-04-0909:53borkdudeNever mind, I think this is enough repro:
(require '[foo.lib :as foo])
(def x #js {:use (fn [x] x)})
(.. x (use foo))
#2020-04-0909:56borkdudeI'm going to verify in #clojurescript if this is idiomatic: using aliases as values#2020-04-0909:56borkdudehttps://clojurians.slack.com/archives/C03S1L9DN/p1586426159359800#2020-04-0910:04borkdude@helios @andrea712 Now I remember. Use can or maybe even should use string namespace names for npm libs:
(require '["foo.lib" :as foo])
(def x #js {:use (fn [x] x)})
(.. x (use foo))
Then this won't give false positives anymore.
#2020-04-0910:08helioscould this be something that we should propose to the clojure style guide?#2020-04-0910:08borkdudepossibly yes#2020-04-0910:05Andreanice!#2020-04-0910:05borkdudeso this works 100% free of errors:
(ns foo
  (:require
   ["markdown-it" :as md]
   ["markdown-it-texmath" :as md-texmath]
   [com.nextjournal.editor.markdown.todo-lists :as todo-lists]
   [com.nextjournal.editor.markdown.gh-preamble :as gh-preamble]))

(def mdit (.. (md #js{:linkify true :breaks false :html true})
              (use md-texmath)
              (use gh-preamble/Plugin)
              (use todo-lists/Plugin)))
#2020-04-0910:06Andreathank you!#2020-04-0916:59seancorfield@borkdude I notice that -main only returns a non-zero exit status for warnings and errors, which means that linter-kondo doesn't attempt to parse the response for any info level reports. What's your reasoning behind that, and how do you view info level linters overall?#2020-04-0917:06borkdude@seancorfield hmm, flycheck does show info level, regardless of the exit code. exit code non zero usually means something is wrong. when you have no errors or warning, nothing is wrong#2020-04-0917:06borkdudewhich is useful for CI environments and pre-commit hooks for example#2020-04-0917:06borkdudeI guess that's on linter-kondo#2020-04-0917:11borkdudeI'm sure gerred will take a PR to change it. ^ @seancorfield#2020-04-0917:12seancorfieldYeah, I might go that route. Was just curious to hear your take on what you expected :info to be used for.#2020-04-0917:13seancorfield@gerred How do you feel about linter-kondo always parsing the output and showing :info level responses?#2020-04-0917:14seancorfield(I don't know how they would map into Atom's annotations on lines etc?)#2020-04-0917:24gerredyeah I'm open to that!#2020-04-0917:25gerredthe last part I'm not sure either, I'd have to look at the core atom linter package#2020-04-0918:16seancorfieldhttps://github.com/gerred/linter-kondo/issues/4 created as a placeholder for that work.#2020-04-0918:17seancorfield(my use case is that I'd like to have missing docstring as :info level so they are still flagged but don't constitute a "failure")#2020-04-0918:25borkdude@seancorfield I guess you can just write a shell script named clj-kondo, put that on your path, exit a non-zero exit code and print some clj-kondo like info lines before exiting, just to see how Atom responds to it.#2020-04-0918:30seancorfield@borkdude linter-kondo doesn't pick up :info at all right now so that wouldn't work.#2020-04-0918:35borkdude@seancorfield Another thought: I bet there is some generic linter package for Atom in which you can point to an executable or script that returns linting output. Maybe: https://atom.io/packages/linter The output that clj-kondo and joker produce is a generally accepted format#2020-04-0918:40seancorfieldI might take a look when I'm not working on other stuff 🙂#2020-04-1009:42borkdudeAaah, light weight type checking.#2020-04-1013:11Adrian SmithI'm looking to build something that enforces specs on data|functions via lsp, do you know if there's a good library in Clojure for LSP? I can see clojure-lsp is using org.eclipse.lsp4j under the hood I can't work out what kondo-clj is using#2020-04-1013:12borkdude@sfyire that code is here. it's based on how clojure-lsp is using the lsp4j library: https://github.com/borkdude/clj-kondo.lsp/tree/master/server#2020-04-1013:12Adrian Smithah cool ty#2020-04-1016:33borkdudeDoes this make sense? Automatically shutting off the unresolved symbol linter in macros? I'm playing with the idea, but it has pros and cons maybe.#2020-04-1016:42seancorfieldIt's a bit of a sledgehammer... I don't think I'd want it to be the default?#2020-04-1017:11seancorfield@borkdude This is puzzling -- I have the following import:
(:import (org.apache.oltu.jose.jws
            JWS$Builder
            signature.impl.SymmetricKeyImpl
            signature.impl.SignatureMethodsHMAC256Impl)))
and these two functions:
(defn signer [] (SignatureMethodsHMAC256Impl.))

(defn symkey [k] (SymmetricKeyImpl. k))
but clj-kondo flags the signature.impl imports as being unused.
#2020-04-1017:13seancorfieldIf I change the import to this, it no longer flags them:
(:import (org.apache.oltu.jose.jws JWS$Builder)
           (org.apache.oltu.jose.jws.signature.impl
            SymmetricKeyImpl
            SignatureMethodsHMAC256Impl)))
#2020-04-1017:36borkdudeFeel free to post an issue about this.#2020-04-1018:37seancorfieldNah, I'm going to bow to clj-kondo's limitation here because nested imports are less readable (and it's already discouraged for requires).#2020-04-1017:31borkdudeclj-kondo apparently doesn't understand that nested import syntax (unlike nested namespace requires, which are discouraged in some style guides). I think I encountered this in tools.reader once and @bronsa's reaction was this: https://github.com/clojure/tools.reader/commit/97d5dac9f5e7c04d8fe6c4a52cd77d6ced560d76#2020-04-1018:32seancorfieldYup, that's basically what I did to that code that was reporting the problem 🙂 It's probably clearer than what I had before anyway.#2020-04-1017:31borkdude^ @seancorfield#2020-04-1017:33borkdudeI guess clj-kondo could add support for it, but I haven't seen it a lot myself out there#2020-04-1017:35borkdudeRe: the macro sledgehammer idea: https://clojurians.slack.com/archives/CHY97NXE2/p1586536435275900 I tried implementing a linter which reports when you use a macro as a value. like (filter when [1 2 3]), but it resulted in quite a lot of false positives since you can pass any symbol to macros without it being resolved as vars.#2020-04-1017:36borkdudeSo I thought it would be useful to capture at least what all used macros in a code base are named so it can be used to suppress certain things#2020-04-1017:39borkdudeBut maybe just a configuration to suppress these, like any other linter, will work, without automatically suppressing anything (which would be optional anyway)#2020-04-1017:41borkdudeIf you're curious what it found and wrote to the cache while linting several libraries:#2020-04-1100:59fabraoHello all, I´m using Atom with clj-kondo, and, is this used to fix the warning/error from editor too, or only to tell?#2020-04-1101:02seancorfieldLinters just tell you what is wrong. How you fix them is up to you 🙂#2020-04-1101:26fabraoI thought it was click to fix integration like in Visual Studio :-)#2020-04-1101:50seancorfieldI've never been comfortable with tools changing my code!#2020-04-1105:46eskosTo be fair, IntelliJ IDEA's autofixes are numerous and extremely useful on the Java side. The bigger problem however is that there might be several potential fixes to any single issue highlighted by the linter, so choosing just one is quite a task... 🙂 Definitely would be an interesting extension project to create though, that is, read in clj-kondo's linting metadata and provide automatic refactoring actions based on those.#2020-04-1119:26AleedIs the cond->> expression meant to be supported? I tried doing something like this, but assoc gives an lint error:
(cond->> initial-map
  (some? x) (assoc :foo bar))
#2020-04-1119:31borkdude@alidcastano
$ clj -e "(cond->> {} (some? 1) (assoc :foo 1))"
Execution error (ClassCastException) at user/eval137 (REPL:1).
clojure.lang.Keyword cannot be cast to clojure.lang.Associative
$ clj-kondo --lint - <<< "(cond->> {} (some? 1) (assoc :foo 1))"
<stdin>:1:30: error: Expected: associative collection or nil, received: keyword.
linting took 10ms, errors: 1, warnings: 0
That seems to be accurate?
#2020-04-1120:10Aleedah interesting, trying it in repl this works:
(cond-> {:x "foo"} 
  true (assoc :y "bar"))
result: {:x "foo", :y "bar"} this doesn’t:
(cond->> {:x "foo"} 
  true (assoc :y "bar"))
error: class clojure.lang.Keyword cannot be cast to class clojure.lang.Associative so i guess it’s not a bug in clj-kondo since clojure throws an error too (thanks for checking it, btw). but unless i’m using cond->> incorrectly looks to be a bug in clojure
#2020-04-1120:12borkdude@alidcastano It's not a bug in Clojure:
user=> (require '[clojure.walk :refer [macroexpand-all]])
nil
user=> (macroexpand-all '(cond->> {:x "foo"} true (assoc :y "bar")))
(let* [G__143 {:x "foo"}] (if true (assoc :y "bar" G__143) G__143))
#2020-04-1120:16Aleedso cond-> evaluates it to (assoc G__143 :y "bar") but cond->> evaluates it to (assoc :y "bar" G__143) 😅#2020-04-1120:34seancorfieldcond->> is thread last so it threads your expression into the last position in the assoc call: (assoc :y "bar" data) which is incorrect usage.#2020-04-1121:08Aleedthanks for further clarifying, i do see now that official Clojure docs state that ->> is the thread last macro. I was reading the cond->> docs in http://clojuredocs.org and incorrectly inferred this was the only difference: threading does not short after the first expression#2020-04-1405:02didibusSo I have basic completion in Emacs going using clj-kondo analyses output#2020-04-1405:03didibusBut now I'm realizing, for completing the vars from the "require" clause, I'll need a better notion of a project. Cause right now I'm just analyzing the buffer, and that gives me the vars in the current buffer, but not the required ones hum...#2020-04-1405:05seancorfield@didibus I'm curious, is this an exercise to see what can be done without a REPL running?#2020-04-1405:08didibusYes#2020-04-1405:09didibusEventually I'd like to complement Cider's nRepl completion with clj-kondo, since they don't always overlap, for example, Cider will not complete until a var is loaded in the REPL (or it'll do so using text completion and just list out all words in the file)#2020-04-1405:10didibusI think it be nice to have completion and jump to definition, and find usages, without nRepl as well, as a fallback,if you don't have nRepl setup.#2020-04-1405:12didibusI guess I can use clj-kondo's own notion of projects, or I could use projectile.#2020-04-1405:17didibus#2020-04-1405:18seancorfieldWell, I'm always happy to see tooling that doesn't rely on the 800lb gorilla (CIDER/nREPL) so this is good work!#2020-04-1405:20didibushaha, ya, while I do love all the power features of cider/nRepl. Sometimes I'd be happy just using inf-clojure, especially if I have clj-kondo for linting and completion and basic jumps. Useful when I remote connect to a REPL that doesn't have nREPL setup for example.#2020-04-1405:24seancorfieldIt's a huge plus point for me to have tooling that works exactly the same locally and remotely without any additional server-side dependencies (and without any code injection).#2020-04-1407:08didibusWhy not code injection? Unrepl style?#2020-04-1416:47seancorfield@didibus when I connect my editor to a Socket REPL running in a production process (or even a QA process), I want it to interfere as little as possible. When we first got started with Clojure, we used to run nREPL servers on QA and production processes with a fair bit of middleware, but it really felt like a "smell" to have all as non-development dependencies. That's why we switched to Socket REPLs and for a while we put up with unrepl injection (of compliment) but now, with the way Atom/Chlorine works, it no longer needs compliment for completion and it is slowly moving away from even the unrepl level of injection which is a good thing as far as we're concerned.#2020-04-1422:49didibusHum, ya that's a fair point for prod REPLs#2020-04-1422:49didibusBut I've looked at some of the Chlorine code, and it seems to all be handled through code injection. How is it going to move away from it without dropping features?#2020-04-1405:31sogaiuusing clj-kondo, alc.index-defs (https://github.com/sogaiu/alc.index-defs) does an initial indexing to produce either tags or TAGS -- these can be used by emacs or whatever other editor has support for them. it works across dependencies as well including handling the namespace prefixes on symbols. so you get jump-to-definition without a repl running and so far it has been pretty accurate. iiuc, in emacs, TAGS info can also be used toward completion. the main downside is that indexing across dependencies takes a while initially. i've used the results in atom, emacs, vim, and vscode.#2020-04-1407:11didibusYa, but I'm not a big fan of TAGS. They're a bit annoying to use. I wanted something more integrated.#2020-04-1407:11sogaiuah, would you mind sharing specifically how you find them to be annoying to use?#2020-04-1407:13didibusIt's two separate process, you have to first run the command to analyse and generate the tags and then tell Emacs where to find the tags. And you kind of have to regenerate them every here and there as you make more changes to the code.#2020-04-1407:14sogaiuyes, that is true. do you have any better ideas for handling the indexing across all of the dependencies?#2020-04-1407:17sogaiui think that the info in the dependencies doesn't change that often. i don't know what's typically the number of files one edits, but it's probably not too many? so a hybrid approach might work out where there is a base-indexing (plus updating when dependencies are updated). for individual file analysis, it may be that clj-kondo is fast enough. also, i wonder if instantaneously updating is really necessary.#2020-04-1407:21sogaiu(btw, i think for the use-case of just reading a code base (especially someone else's), i don't think the initial indexing is too much of a price to pay)#2020-04-1407:21didibusHum, well I am just starting to think about it#2020-04-1407:21didibusYa, for reading and navigating TAGS are nice#2020-04-1407:22didibusRight now I call clj-kondo to analyse the current buffer on every completion-at-point invocation.#2020-04-1407:23didibusSeems pretty fast, for single files, clj-kondo takes less than 100ms to complete. But I'm guessing it might take longer when run on a project#2020-04-1407:24sogaiunice! may i ask what the typical buffer sizes you have tried with? what i try to benchmark against for editor type stuff is clojure.core.#2020-04-1407:24sogaiuwhen i feel like feeling pain i go for clojurescript's core 🙂#2020-04-1407:24didibusHaven't tried clojure.core yet, I thought I should since that namespace is huged, probably at the upper bound on the size that you'll find at large#2020-04-1407:25borkdudeclojure.core is probably not typical for most projects#2020-04-1407:25sogaiuyes, i have over 100,000 clojure files here and clojure.core is definitely not typical 🙂#2020-04-1407:25didibusHow is clj-kondo handling the cache?#2020-04-1407:26didibusDoes it skips files that haven't been touched since last time they were linted/analyzed?#2020-04-1407:26borkdude@didibus Your editor drives how clj-kondo is invoked. clj-kondo just does what it is told to by the editor#2020-04-1407:27borkdudeit doesn't look at newer since last linted or anything like that, it just lints a file it is told to lint#2020-04-1407:28didibusWhat about when told to lint a directory? Like how it can find the root with .clj-kondo to identify the project and lint the entire project#2020-04-1407:29borkdude@didibus To lint an entire project including dependencies you typically invoke it like:
PROJECT_ROOT $ clj-kondo --lint $(clojure -Spath)
#2020-04-1407:29borkdudeclj-kondo looks from the current working dir upwards to find a .clj-kondo directory#2020-04-1407:32didibusSo when it lints mutliple files at a time like that, like say given a directory or using a full classpath, what is the cache used for?#2020-04-1407:34borkdude@didibus the cache is more or less a database with information which is used for linting, like arities from library functions#2020-04-1407:35didibusBut it should in theory make re-linting a full project a second time faster correct? Or does it serve a different purpose?#2020-04-1407:35borkdudeno, it's not used like that. it's only used to hold on to information that it's seen before#2020-04-1407:37didibusHum, I'm not sure I understand that part. If it's afterwards looking for that info again, it would first find it in the cache and so wouldn't need to recompute it? Is that right? So wouldn't that make it faster?#2020-04-1407:38borkdudesay you are linting library cheshire. it finds cheshire.core and now it saves the fact that cheshire.core/generate-string takes x arguments to the cache. when you are using this function from your editor and call it with n != x args, you will get a lint warning, because clj-kondo was able to get that information from the cache. the cache is not used to preventing files from being linted again.#2020-04-1407:39borkdudea better name is really "db"#2020-04-1407:42didibusAh ok. Ya so I understand that. Let me put my question a different way. If I generate analyses for a full project, by doing clj-kondo --lint (clojure -Spath) --config {:analyses true}I know I got the config command wrong but you get the point. And after doing that, I have clj-kondo analyse one single file from that same project. Would that analyses now be faster?#2020-04-1407:43borkdudethe analysis itself doesn't go any faster, it just lints that single file#2020-04-1407:44borkdudeit also doesn't return the analysis information for anything but that single file#2020-04-1407:45didibusOk ya I see. But it seems the cache might have all that's the needed for the require namespaces "analyses"? How hard do you think it would be for the analyses feature to be extended to support say an additional argument that also includes in it's output the var-definitions of the required namespaces?#2020-04-1407:47borkdude@didibus I think clj-kondo should be fairly agnostic about what you do with the analysis information. For your purposes it might be better to process the analysis output, extract only the information you need and save it elsewhere (possibly also in the .cache directory). Then make incremental updates to that using the analysis output of the single file.#2020-04-1407:47borkdudeProcessing the analysis output of the entire project on every completion will be more expensive than pre-processing it once.#2020-04-1407:48didibusSo after analysing a file, the current cache does not already contain its list of var-defs?#2020-04-1407:49didibusI guess I'm just trying to see if I'm just.going to recreate a cache for what clj-kondo already caches.#2020-04-1407:49borkdude@didibus clj-kondo does not use the analysis export internally, the information in the cache is slightly different, so it cannot provide you the analysis export from other namespaces, even if they are in the cache.#2020-04-1407:49borkdudealso the information from the cache itself is an implementation detail one should not rely on#2020-04-1407:50didibusYa I guess that's a fair point#2020-04-1407:50borkdude(i.e. one should not reverse engineer the transit files and expect that to keep working over versions)#2020-04-1407:54didibusSo what you said above was my idea. I'd just analyse a whole project probably when you initialize the minor mode in a buffer, and also maybe on changing the deps.edn, project.clj, and such file afterwards. Cache for each file the analyses data as well as the file last modified timestamp. And then on completion I'll ask clj-kondo to analyse the current buffer, where I'll update the cache for the current file with its result, and then grab the var-definitions of that file and all it's required file from the cache and merge them for the completion list I give Emacs#2020-04-1407:55borkdudeYep. Where cache = the thing specialized for your purposes.#2020-04-1407:55sogaiubtw, typical times for analyzing the whole project range in the minutes here#2020-04-1407:55sogaiuthat's including depdencies#2020-04-1407:55didibusYa, my own cache, not clj-kondo's#2020-04-1407:55sogaiusorry, that's including the post-analysis phase#2020-04-1407:56borkdude@sogaiu I would say that's fairly untypical too, clj-kondo can lint itself including deps in 10s#2020-04-1408:05sogaiuyou're right -- i'm misremembering. though the total times i see can exceed 20s if including the post-analysis work. the point i'm trying to make is that this is not a great duration from the perspective of editor use. one might want to parallelize or work in the background.#2020-04-1408:37borkdudeyeah, see the pmap branch#2020-04-1407:58didibusHum...#2020-04-1407:58sogaiuthat is about what i get for clj-kondo, yes#2020-04-1407:58didibusMaybe I should analyse things as they are encountered in the buffer instead#2020-04-1407:59sogaiuclj-kondo is not that large#2020-04-1407:59sogaiuas awesome as it is 🙂#2020-04-1407:59borkdude@didibus Yes, analyze per buffer, but an initial lint of dependencies can be on demand#2020-04-1407:59didibusLike when you open a file in the editor, on opening the file I'd analyse the file, and then analyse the files from its require.#2020-04-1407:59didibusIn an async process and cache that#2020-04-1408:00didibusThen all completion is looked up in the cache#2020-04-1408:00didibusThat should amortize for the user the amount of time he's ever waiting#2020-04-1408:01didibusCan clj-kondo work in parallel? Or would it trip up?#2020-04-1408:01didibusIf say I use 4 clj-kondo process at a time linting different files?#2020-04-1408:04didibusAnyways, I think one or more combination of these ideas would probably work well enough. I'll see how far I can get on that in the next few weeks#2020-04-1408:05sogaiubtw, here's some distribution of file sizes across clojars-fetched clojure source:
1k:  73042
  2k:  22604
  4k:  16474
  8k:   7887
 16k:   3027
 32k:   1014
 64k:    331
128k:    108
256k:     21
512k:      6
  1M:      2
  4M:      3
#2020-04-1408:06sogaiuso the majority of things seem to be under 1k#2020-04-1408:08didibusThat's good#2020-04-1408:33borkdude@didibus I have one issue in the clj-kondo issue tracker for linting in parallel. This work is in the pmap branch. It seems to work (using pmap), but there is one strange issue when I pmap over the sources of a jar file. Linting a directory does work. I still have to get to the bottom of this#2020-04-1512:18sogaiu@borkdude thought you'd appreciate this quote from a classic paper on incremental parsing#2020-04-1513:32orestisSo Malli showed a pretty nifty sneak peek of clj-kondo integration, where you could define the inputs and outputs of a defn and kondo could somehow lint their usage. Is that something that kondo can do today? And if yes, do the types “flow” down to functions calls etc?#2020-04-1513:32borkdude@orestis They are using the format described here: https://github.com/borkdude/clj-kondo/blob/master/doc/types.md#2020-04-1513:33borkdudeyes, the types "flow" in let and function return types#2020-04-1513:33orestisMy use case is, I have some functions whose arguments can be described pretty tightly (they are GraphQL objects). I’d like to be able to catch mistypes, checking for keys that aren’t there (closed types) etc. Doing it at the syntax level like demonstrated would be cool, but I could also do it on my own.#2020-04-1513:35orestisSome example:
(defn my-resolver [context args _]
  (let [subtype (:foo args)]
    (deal-with-subtype context subtype (:bar args))))
#2020-04-1513:35borkdude@orestis there is this now: {:op :keys, :req {:a :string} :opt {:b :int}}, but that's mostly for checking map literals at callsites#2020-04-1513:36borkdudenot sure how well that works with "flow", I expect it not to work at all at the moment.#2020-04-1513:36orestisCan I somehow “lint” that :foo is actually part of some spec? Can I somehow lint that the third argument deal-with-subtype ( (:bar args) ) is a sub-spec of the bigger spec?#2020-04-1513:37orestisSorry if this sounds too vague, I don’t have the terminology figured out…#2020-04-1513:37borkdudeI have currently one function in clj-kondo that is typed using the :keys: https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/findings.types.edn No, there is no spec-like thing#2020-04-1513:38orestisWhere spec could be malli -> which is what piqued my interest#2020-04-1513:39orestisI don’t necessarily want to have clj-kondo itself do this, but it seems like it may be generating information I could then piece together on my own? Or would I go to tools.analyzer for this?#2020-04-1513:41borkdude@orestis clj-kondo doesn't generate any type information#2020-04-1513:41borkdudeafk now, ttyl#2020-04-1513:42orestisNp, I’ll see if I can explain myself better in some clojureverse post 🙂 Thanks#2020-04-1606:06tatutjust found out clj-kondo datalog query linting (by having a missing var)... very cool#2020-04-1608:12didibus@borkdude Am I just not seeing it, or does analysis not contain the list of refered vars? Like if I want to know what vars a namespace has refered (ns (:require [some :as foo :refer [bar baz]])) and I want to get bar and baz ?#2020-04-1608:38didibus@borkdude Also... hum, does clj-kondo track keywords? If so, could the analysis contain information about them as well? Like what are all the keywords in the code, and where they are used#2020-04-1608:39borkdude@didibus The analysis data only contains what is documented here: https://github.com/borkdude/clj-kondo/tree/master/analysis#2020-04-1608:39borkdudeCould more be added? Sure. Make an issue with a proposal.#2020-04-1608:40didibusOk, will do, thx#2020-04-1719:18practicalli-johnI love the "Expected: function, recieved: seq" warning I just got. That has certainly saved me a lot of time today. Thank you.#2020-04-1812:50Chris O’DonnellI'm seeing some odd behavior with a :lint-as rule. In my config, I have {:lint-as {com.fulcrologic.fulcro.components/defsc clojure.core/defn}}. Oddly enough, I get an unused namespace warning for df with the form
(defn Home [_this _]
  {:lifecycle-method (df/load! "foo")}
  (dom/div {} "Home"))
but not with
(defsc Home [_this _]
  {:lifecycle-method (df/load! "foo")}
  (dom/div {} "Home"))
Interestingly, I uncovered this because I was getting an unused namespace warning for df with
(defsc Home [_this _]
  {:query []
   :ident nil
   :initial-state nil
   :route-segment []
   :will-enter (fn [app _]
                 (df/load! app [:component/id :created-gift-lists]
                   ui.gift-list/CreatedGiftLists))}
  (dom/div {} "Home"))
However, this warning goes away if I delete any of the keys from the component options map (other than :will-enter of course).
#2020-04-1812:51borkdude@codonnell Maybe it's because clj-kondo tries to parse the first map in defn as a pre-post map#2020-04-1812:52Chris O’DonnellAh, that's a good thought.#2020-04-1812:52borkdudebut it's a bug nonetheless probably#2020-04-1812:53Chris O’DonnellHappy to make a github issue if that would be helpful#2020-04-1812:53borkdudeyes please#2020-04-1813:05Chris O’Donnellhttps://github.com/borkdude/clj-kondo/issues/858#2020-04-1813:06borkdudethanks!#2020-04-1813:06Chris O’DonnellSure thing, thanks for all the work you've put into clj-kondo! 🙂#2020-04-1816:18FlavaDavehaving trouble getting kondo to work I installed with homebrew and ~/.lein/profiles.clj looks like
{:user
 {:dependencies [[clj-kondo "RELEASE"]]
  :aliases {"clj-kondo" ["run" "-m" "clj-kondo.main"]}}}
lein clj-kondo --lint src works and returns errors in command line, but there is no linting going on in my editor.
#2020-04-1816:21borkdude@dgonsalves22 I don't recommend running clj-kondo with leiningen for editor integration. Installing the binary is a much faster and better experience#2020-04-1816:22FlavaDaveok. I installed with brew and it is in bin/. is that not what i should be doing?#2020-04-1816:24borkdude@dgonsalves22 If you installed it with brew, and it's on your path, then you're set. But it depends on your editor if you enable the right plugin, etc. What editor are you using?#2020-04-1816:24FlavaDavespacemacs#2020-04-1816:25borkdude@dgonsalves22 check this out: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#spacemacs#2020-04-1816:34borkdude@dgonsalves22 Also the people in #spacemacs are really helpful about clj-kondo#2020-04-1816:48FlavaDavethanks @borkdude#2020-04-1817:36lvhHi! I'm trying to disable a particular checker for some source files (my tests touch private vars and that's intentional/OK), and I figured a separate config file would work. It seems to work locally on my machine, but DeLaGuardo//cdn-cgi/l/email-protection appears to be ignoring the command line option: https://github.com/latacora/wernicke/runs/598161720?check_suite_focus=true#2020-04-1818:30borkdudeMaybe ask @U04V4KLKC if he can support additional command line args. Or roll your own thing. See https://github.com/borkdude/clj-kondo/blob/master/doc/ci-integration.md#linter-output-integration#2020-04-1819:43delaguardoHi) cli args should work as expected. I'll check this tomorrow#2020-04-2113:48delaguardo@lvh please check DeLaGuardo/ I changed how the options passed to runner internally. Now it should respect your configuration#2020-04-2117:24lvhfyi there appears to be a typo here: https://github.com/DeLaGuardo/clojure-lint-action/blob/dbba6c8a6c492b664882be853fe132a62ac6cfe5/action.yml#L14#2020-04-2117:25lvhthis didn't fix the issue for me#2020-04-2117:25lvhhttps://github.com/latacora/wernicke/runs/605960762?check_suite_focus=true#2020-04-1817:36lvhI considered trying a YAML vector of args instead of a single string but if that was the issue, --lint src working wouldn't make sense either#2020-04-1817:40lvh
(base) 
#2020-04-1817:40lvh(that's locally, works fine)#2020-04-1818:03FlavaDave@borkdude just to follow up. My previous issues were definitely spacemacs related and not kondo related. Thought you would like to know.#2020-04-1818:24borkdude@lvh To disable this linter in specific namespaces you can use one of these two ways:
(ns foo)

(defn- foo [])
(foo)

(ns bar
  {:clj-kondo/config {:linters {:private-call {:level :off}}}} ;; 1
  (:require [foo]))

(foo/foo)   ;; 1
(#'foo/foo) ;; 2
#2020-04-2014:14borkdude@lvh Did this work for you?#2020-04-2117:23lvhhey! yeah I managed to work around the bug in the github action w/ this, thank you!#2020-04-1915:41hindolHi, clj-kondo does not complain on namespace qualified keywords even when the namespace is not required. Is this intended?#2020-04-1915:42borkdudeDo you mean like:
$ clj-kondo --lint - <<< '::f/foo'
linting took 9ms, errors: 0, warnings: 0
#2020-04-1915:43borkdudeYeah, I think it should warn about that. Please make an issue#2020-04-1915:43hindolYes#2020-04-1916:16martinklepsch
(let [y (str "y")]
  (string/replace "abc" #"[a]" y))
This produces the following error on y for me:
Regex match arg requires string or function replacement arg.
#2020-04-1916:24borkdude@martinklepsch Could this be an older version of clj-kondo? I remember fixing something like this#2020-04-1916:24borkdudeplz upgrade#2020-04-1916:25martinklepschI’ll give that a try and report back#2020-04-1916:36martinklepsch👍 works as expected#2020-04-2008:38helioshttps://github.com/didibus/anakondo#2020-04-2009:22martinklepschIs there a recommended way to address error: unresolved symbol goog.DEBUG ?#2020-04-2009:22martinklepschIt’s not something you usually require so I’m not sure how to tell clj-kondo that it’s fine#2020-04-2009:24martinklepsch
{:linters
  {:unresolved-symbol
    {:exclude [(riemann.streams/streams [where])]}}}
I guess something like this but for just the goog.DEBUG symbol. I’ll give variations of this a try
#2020-04-2009:36borkdude@U050TNB9F Just adding that symbol to the :exclude vector works#2020-04-2009:36borkdudebut I would be happy to support this out of the box. There is also goog.global which I listed.#2020-04-2009:37borkdudeMaybe everything that starts with goog. should be not warning about in CLJS or is that too much?#2020-04-2009:38borkdudeIf you grep the source for goog.global you'll find the spot where this is handled. Feel free to add more there.#2020-04-2009:52martinklepschI think everything under goog. would be to aggressive since that would not err if goog.abc is used via it’s fully qualified name in namespace A but only require in namespace B#2020-04-2009:54martinklepschI found multiple places that mention goog.global , would it need to be added to both?
extract/clj_kondo/impl/extract_var_info.clj
58:        special '#{ns js* *target* goog.global}]

src/clj_kondo/impl/var_info_gen.clj
10:  (def cljs-core-syms '#{,,, goog.global ,,,})
#2020-04-2009:55borkdude@U050TNB9F Only to the first one. The second one is generated#2020-04-2009:55martinklepsch👍#2020-04-2009:56borkdudeYou can then run script/extract-var-info to update the second one#2020-04-2009:56juhoteperiI think anything in goog/base.js is accessable like this. In addition to global and DEBUG, LOCALE is probably quite common property: https://github.com/google/closure-library/blob/master/closure/goog/base.js#2020-04-2009:57juhoteperiThough I guess LOCALE is set in :closure-defines so it isn't usually referred in the code#2020-04-2112:01hindolclj-kondo warns about unresolved symbols in macros,
(defmacro when-let*
  ([bindings & body]
   (if (seq bindings)
     `(when-let [~(first bindings) ~(second bindings)]
        (when-let* ~(drop 2 bindings) 
Is this within the scope of clj-kondo?
#2020-04-2112:03borkdude@hindol.adhya You can use the :lint-as configuration here#2020-04-2112:03borkdudeSee https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#lint-a-custom-macro-like-a-built-in-macro#2020-04-2112:08hindol:clj-kondo/config goes to the ns defining the macro or the one using it?#2020-04-2112:08borkdudeusing. just put :lint-as in .clj-kondo/config.edn#2020-04-2112:10hindolIf it were the ns defining it, the macro and the config for linting could be together. But in this case, will just use .clj-kondo/config.edn#2020-04-2112:11borkdudethat would only work if you would lint all the sources in your project including dependencies. clj-kondo is designed to be able to lint single files as well#2020-04-2112:12hindolYeah, that makes sense.#2020-04-2112:54flefikHad some trouble installing clj-kondo today after following the instructions in the README. /usr/local/bin is not always writable, and there seems to be some race condition too in the installation script when running it against a temporary file.
~ % bash <(curl -s )            
Downloading  to /tmp
Moving /usr/local/bin/clj-kondo to /usr/local/bin/clj-kondo.old
mv: cannot move '/tmp/clj-kondo' to '/usr/local/bin/clj-kondo': Permission denied
~ % sudo bash <(curl -s )       
bash: /proc/self/fd/11: No such file or directory
~ % (23) Failed writing body
~ % curl  > install-clj-kondo.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1992  100  1992    0     0  24292      0 --:--:-- --:--:-- --:--:-- 24000
~ % ./install-clj-kondo.sh 
zsh: permission denied: ./install-clj-kondo.sh
~ % chmod +x ./install-clj-kondo.sh
~ % sudo ./install-clj-kondo.sh
Downloading  to /tmp
Successfully installed clj-kondo in /usr/local/bin
#2020-04-2113:11borkdude@cfeckardt you can invoke it like this:
install [--dir <dir>] [--download-dir <download-dir>]
does that not work for you?
#2020-04-2115:13flefiki saved it to a file (install-clj-kondo.sh) then ran it as sudo and that worked#2020-04-2115:13flefikbut neither bash <(curl -s ) nor sudo bash <(curl -s ) worked.#2020-04-2115:14flefikthis was on ubuntu 19.04#2020-04-2115:16borkdudeok, maybe updating the README to not use bash <(...) is a better idea then#2020-04-2115:31flefikI think sudo and <() don’t play nice#2020-04-2115:34flefiksudo bash -c "$(curl -s )"#2020-04-2115:56borkdude@cfeckardt Changed it: https://github.com/borkdude/clj-kondo/commit/6f3c7a52939bf6a96d22287b34441ccc01ebd0f9#2020-04-2208:23martinklepschDoes anyone know if there’s a way to make warnings non-fatal in the DeLaGuardo/ GH action?#2020-04-2208:32delaguardocan you share your action output? currently action should exit with 0 exit code in case “warnings only | no errors”#2020-04-2208:38martinklepschYes, it’s doing that. The task itself exists with 0 (i.e. passes) but the “clj-kondo check” has warnings and is marked as failing:#2020-04-2208:39delaguardook, got it. I will check github’s api#2020-04-2208:40martinklepschThanks you!!#2020-04-2211:24delaguardoI used “neutral” check status to indicate that there are some warning. What do you think?#2020-04-2211:27delaguardoyou can test it from the branch DeLaGuardo/#2020-04-2211:27martinklepschYes, I think that would make sense to me, perhaps it could also be configurable?#2020-04-2211:28martinklepschI guess it would be nice to be able to see when you previously had no warnings but a given change introduces some#2020-04-2211:28martinklepschbut I guess then it would go from green to gray#2020-04-2211:28martinklepschSo maybe config isn’t actually required#2020-04-2211:31delaguardoGH check-run status is a bit restrictive#2020-04-2211:33martinklepschCool makes sense. I guess once we’ve fixed all warnings we might want the status to be “Failed” when new warnings are introduced. But “Neutral” is also ok for now.#2020-04-2211:34delaguardoI would like to keep the config as small as possible. don’t think the option like what to do in case of neutral status make a lot of sense.
#2020-04-2211:35delaguardoalso it is not possible in general to get status of previous check-run because GH can mark it as stale#2020-04-2211:36martinklepschYeah I mean more like being able to tell the action to use “Failed” or “Neutral” state when there are warnings#2020-04-2211:37martinklepschHave you considered filtering warnings so that they are only added to changed lines?#2020-04-2211:39delaguardoyes, and this is possible, already checked that out#2020-04-2211:40delaguardojust need more time to finish#2020-04-2211:50borkdude@U050TNB9F What if you change the arity of a function and don't change callsites accordingly? Then you won't be warned about that?#2020-04-2211:51martinklepsch@U04V15CAJ good point! but I guess that would be an error and errors should always be shown#2020-04-2211:52borkduderight#2020-04-2211:52borkdude@U050TNB9F Some people use ReviewDog to accomplish only being warned about new warnings and errors#2020-04-2211:54borkdudeJUXT are doing this. Here is their config: https://github.com/borkdude/clj-kondo/issues/844#issuecomment-609827001#2020-04-2208:27delaguardoI’m working on it right now)#2020-04-2215:15mauricio.szaboHi, I was looking if there's any way to make kondo ignore a specific namespace "required but never used". Also, I think I found a bug - clj-kondo warns that this required is never used, but down below the code it is being used: https://github.com/mauricioszabo/atom-chlorine/blob/master/src/chlorine/repl.cljs#L8#2020-04-2215:21borkdude@mauricio.szabo I think this is caused by:
[chlorine.ui.atom :as atom]
[repl-tooling.editor-integration.evaluation :as e-eval]
["atom" :refer [CompositeDisposable]]
so now atom becomes ambiguous
#2020-04-2215:27mauricio.szaboBecause of "atom" require, or because atom (the alias) becomes ambiguous with the function?#2020-04-2215:28borkdudethe alias is ambigious because there is a namespace called atom but also a namespace alias atom#2020-04-2217:21mauricio.szaboI don't understand, to be honest. The namespace, you mean, is the "atom", as string? Because that's a javascript require...#2020-04-2217:48borkdude@mauricio.szabo I think we can reproduce the bug simply in terms of normal Clojure:
(ns a) (def x :a)
(ns b) (def x :b)
(ns c (:require [a :as b] b))
b/x
This says that namespace a is unused, while in reality, it's b that's unused. So aliases have preference over full namespace names
#2020-04-2217:49borkdudeI'll make an issue#2020-04-2217:49borkduderenaming your alias to something else will fix this for now#2020-04-2217:51borkdudehttps://github.com/borkdude/clj-kondo/issues/864#2020-04-2218:25borkdude@mauricio.szabo Fixed on master#2020-04-2218:27mauricio.szaboWow, already? Thanks a lot 👍#2020-04-2317:41martinklepschIs there a way to prevent certain warnings from being reported e.g. don’t report unused-namespace in general or similar?#2020-04-2317:44martinklepschI assume that would be possible with :linters? 😄#2020-04-2317:52borkdude@martinklepsch {:linters {:unused-namespace {:level :off}}}#2020-04-2317:52borkdude@martinklepsch But for that specific linter: if you do not use an alias for your namespace, e.g. (require '[foo.specs]), then the namespace won't be reported#2020-04-2317:53borkdudeit's also possible to disable that linter in one namespace only using metadata#2020-04-2318:21martinklepschNah, we need to disable it everywhere for now 😛#2020-04-2318:21martinklepschThank you!#2020-04-2323:28didibus@borkdude Is clj-kondo able to do any kind of local analysis? Like given a form, can it identify the local bindings?#2020-04-2401:14whiloHey @borkdude, we have released a new version of the Datalog parser: https://github.com/lambdaforge/datalog-parser/ for our next release of Datahike. It now supports more of Datomic's Datalog like pagination and limits. Feel free to bump the dependency in clj-kondo when you have the time.#2020-04-2407:27borkdude@whilo A PR is welcome along with maybe a test which tests one of the new things?#2020-04-2407:28borkdude@didibus It does that analysis, but it doesn't expose it.#2020-04-2407:30didibusOk I see. And, is it able to know the type hints of vars including locals?#2020-04-2407:32didibusRight now I added a pure Emacs based local auto-complete, works pretty well, especially since it handles unbalanced forms. But I'm trying to add java auto-complete, and if I wanted to auto-complete the methods, I'd need to know the type hint of the local ideally.#2020-04-2407:32didibusSo I'm not sure I'd benefit from clj-kondo local analysis, but I guess I'm curious what it has, maybe there's some good stuff in there I could use 😄#2020-04-2407:34borkdudeclj-kondo currently only analyzes arities from standard Java classes and only when you're calling a static method.
$ clj-kondo --lint - <<< '(Thread/sleep 1 2 3)'
<stdin>:1:1: error: java.lang.Thread/sleep is called with 3 args but expects 1 or 2
linting took 12ms, errors: 1, warnings: 0
#2020-04-2407:34didibusOh, I didn't even know it did that. Cool!#2020-04-2407:35didibusI'm actually using jar and javap for java, not clj-kondo as of now, thought clj-kondo had no java support whatsoever#2020-04-2407:36borkdudeit's limited. I analyzed these arities from javadoc sources, but I want to migrate it to some reflection based solution maybe one day. but in practice I don't see these java arity errors that often, so maybe it's not worth putting time in this#2020-04-2407:37didibusWhat I could use is if clj-kondo analysis could list the java imports in a given namespace, and it if could tell me the type hint of vars and local bindings#2020-04-2407:38borkdude@didibus I think the imports are good to add, you already made an issue for it right? Type hints: it doesn't have that information#2020-04-2407:39didibusNo I made one for refer, I'll make one for imports#2020-04-2407:39borkdudeor maybe I'm misunderstanding something about the type hints#2020-04-2407:40didibusI'm thinking something like:
(let [^SomeClass a]
  (-> a (.method 1 2)))
#2020-04-2407:41didibusAnd clj-kondo can tell me the local a is of type-hint SomeClass#2020-04-2407:42didibusThat way maybe I could take a stab at listing the methods for it. But I don't know, might not be worth the effort.#2020-04-2407:42borkdudehmm, it might have that information because:
$ clj-kondo --lint - <<< '(defn foo [x] (let [^String y x] (inc y)))'
<stdin>:1:39: warning: Expected: number, received: string or nil.
#2020-04-2407:43borkdudebut it doesn't remember the exact class, only if it matches one of the types that the "type system" can handle#2020-04-2407:43borkdudebut it could maybe be made so#2020-04-2407:44didibusAnd possibly the same for globals:
(defn get-bla ^Bla [a] ...)
And on the var-definition it would say: :type-hint "Bla" something like that
#2020-04-2407:46didibusIn any case, wouldn't say its the highest on the list of priority#2020-04-2408:50whilo@borkdude We already test that in our repository. The only thing you need to do is bump the dependency. I can open a PR for that if you prefer that.#2020-04-2408:52borkdudesure, thanks!#2020-04-2408:52borkdudeI just wondered if there is anything new that clj-kondo catches and if this should be mentioned in the release notes#2020-04-2409:54yendaclj-kondo doesn't macro expand? it reports a lot of error such as error: status-im.utils.email/send-email is called with 2 args but expects 3 where send-email is a defined with a macro that creates a multi-arity fn taking 2 or 3 arguments#2020-04-2409:56borkdude@yenda clj-kondo only expands a selected set of macros from clojure.core and some popular community libraries. See - https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#lint-a-custom-macro-like-a-built-in-macro - https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-unresolved-symbols-from-being-reported how to deal with this#2020-04-2409:56yendathank you!#2020-04-2410:31yendait looks like it doesn't like the ^number tag either unresolved symbol number#2020-04-2410:34yendaswitching from cljfmt to clj-kondo we get 600 warning 😄 from the doc it doesn't look like there is an equivalent of cljfmt fix in clj-kondo?#2020-04-2410:37borkdude@yenda can you give more context?
user=> (fn [^number x])
Syntax error (IllegalArgumentException) compiling fn* at (REPL:1:1).
Unable to resolve classname: number
is this CLJS maybe?
#2020-04-2410:37yendayes#2020-04-2410:38yendawitout it you get compilation errors#2020-04-2410:38yenda
File: /home/yenda/status-react/src/status_im/ethereum/ens.cljs:108:27
--------------------------------------------------------------------------------
 105 |         ;; a length of 32 bytes
 106 |         ;; 1 byte is 2 chars here
 107 |         [next-field-length-hex raw-hash-rest] (split-at 64 raw-hash-rest)
 108 |         next-field-length (* (abi-spec/hex-to-number (string/join next-field-length-hex)) 2)
---------------------------------^----------------------------------------------
Error in phase :compilation
cljs.core/*, all arguments must be numbers, got [#{nil clj-nil} number] instead
{:warning :invalid-arithmetic, :line 108, :column 27, :msg "cljs.core/*, all arguments must be numbers, got [#{nil clj-nil} number] instead"}
ExceptionInfo: cljs.core/*, all arguments must be numbers, got [#{nil clj-nil} number] instead
#2020-04-2410:38borkdudein CLJS I don't get an error about this:
$ clj-kondo --lint - --lang cljs <<< '(fn [^number x] x)'
linting took 12ms, errors: 0, warnings: 0
#2020-04-2410:39borkdude@yenda Please make a small repro#2020-04-2410:39yendaI get it for this line: next-field-length (* ^number (abi-spec/hex-to-number (string/join next-field-length-hex)) 2)#2020-04-2410:39borkdudeCan you make a repro, a small file that I can execute/lint locally?#2020-04-2410:40yendayes will try first this --lang cljs option#2020-04-2410:40yendamaybe that's it#2020-04-2410:40borkdudewell clj-kondo should recognize that from the .cljs extension, so that's probably not it then#2020-04-2410:41yendayeah I still get src/status_im/ethereum/ens.cljs:108:31: error: unresolved symbol number#2020-04-2410:42yenda
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "78011d161c19381c1d0b130c1708"}, :content ("[email protected]")}
#2020-04-2410:42yendait doesn't like the inline tagging#2020-04-2410:43borkdudeit should probably be added here: https://github.com/borkdude/clj-kondo/blob/846bdb9a4f5f2b39bb6e96c6b3a7f3a4c9afcd0c/src/clj_kondo/impl/metadata.clj#L31#2020-04-2410:43borkdudeissue + PR for this is welcome#2020-04-2410:44borkdudeFor now you can use:
$ clj-kondo --lint - --config '{:linters {:unresolved-symbol {:exclude [number]}}}'  <<< '(fn [x] (* ^number x 1))'
linting took 10ms, errors: 0, warnings: 0
#2020-04-2410:45yendayea that is what I did#2020-04-2410:49yendaok added an issue might give a shot to a pr later#2020-04-2410:50borkdudethanks#2020-04-2410:51yendaso there is no equivalent of cljfmt fix that automatically fixes the warnings right?#2020-04-2410:51borkdudeno#2020-04-2609:51borkdudePodcast about clj-kondo and other topics: https://www.therepl.net/#2020-04-2610:23hindolWhat does this line #!/usr/bin/env clojure -Sdeps {:deps,{selmer,{:mvn/version,"1.12.17"},clj-kondo,{:mvn/version,"2020.04.05"}}} do? From clj-kondo.lsp/script/update-project.clj. I get a warning /usr/bin/env: 'clojure -Sdeps {:deps,{selmer,{:mvn/version,"1.12.17"},clj-kondo,{:mvn/version,"2020.04.05"}}}': No such file or directory because I don't think that's a valid shebang line.#2020-04-2610:25borkdude@hindol.adhya That might be a difference between macOS and linux. on macOS a shebang can take arguments. But this is easily fixable.#2020-04-2610:25borkdude@hindol.adhya Like this:
#!/bin/sh

#_(
   "exec" "bb" "$0" hello "
#2020-04-2610:26borkdudePR welcome#2020-04-2610:30hindolSure. A PR's coming your way. I thought creating a deps.edn in the same directory would fix it as well, but that didn't work.#2020-04-2610:33borkdudehmm, why didn't it?#2020-04-2611:15hindolAt first glance, using clojure that way, it's downloading the deps but not building the classpath right.
Could not locate selmer/parser__init.class, selmer/parser.clj or selmer/parser.cljc on classpath.
#2020-04-2611:23hindol@borkdude How about just sed "s/{{version}}/$(cat vscode-extension/CLJ_KONDO_VERSION)/g" server/project.clj.template > server/project.clj? Should work on MacOS as well.#2020-04-2611:30borkdude@hindol.adhya I pushed the fix for linux#2020-04-2611:48hindolStill does not work on my system.
Syntax error (FileNotFoundException) compiling at (script/update-project.clj:1:1).
Could not locate selmer/parser__init.class, selmer/parser.clj or selmer/parser.cljc on classpath.
And no server/project.clj is created (I deleted the on from git).
#2020-04-2611:52borkdude@hindol.adhya How do you start the script?#2020-04-2611:53hindol./script/build-server#2020-04-2611:44hindolOkay, I was preparing a PR but good that you fixed it.#2020-04-2612:01borkdude@hindol.adhya This works for me on Debian with commit 7f15c58512dd347cf9e537120a942d8aaf9e2861:
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "96f4f9e4fdf2e3f2f3d6e0e6e5a7afa7ae"}, :content ("[email protected]")}
#2020-04-2612:04hindolI am on Ubuntu Focal under Windows WSL, but the WSL part should not matter. It works just like plain Linux.#2020-04-2612:05hindolInstalled clojure via Linuxbrew.#2020-04-2612:09borkdudeI tested it on a debian machine where I never ran this repo before and it worked the first time. I'm not sure why it doesn't work for you. Can you try deleting + cloning from scratch?#2020-04-2613:06hindolDid work after cloning from scratch.#2020-04-2616:22nonrecursivehi hi - i’m using and loving clj-kondo 🙂 i’m trying to disable the :unused-namespace linter from within a namespace without success, i’ve added {:clj-kondo/config ^:replace {:linters {:unused-namespace {:exclude ["."]}}}} as metadata. I’ve also tried {:clj-kondo/config ^:replace {:linters {:unused-namespace {:level :off}}}}. any idea of what would help?#2020-04-2616:24borkdudeHi @nonrecursive - thanks and welcome.#2020-04-2616:24borkdude@nonrecursive Can you post a repro of an entire (small) file, so we can talk about exactly the same code?#2020-04-2616:26nonrecursivesure thing, thank you very much!#2020-04-2616:27borkdudeworks like a charm over here. which version are you using?#2020-04-2616:27borkdudebtw, ^:replace isn't necessary here#2020-04-2616:28nonrecursivelooks like i’m on v2019.12.14#2020-04-2616:28borkdudeplease upgrade#2020-04-2616:29borkdudealso note that only namespaces required with an alias or refer are reported. so (:require [foo.specs]) is fine#2020-04-2616:29nonrecursivelooks like that did it!! so easy. thank you!#2020-04-2616:29nonrecursiveah, nice#2020-04-2616:30nonrecursivewhat i’m actually doing is creating a dev namespace with a lot of aliased namespaces pulled in to put them within easy reach#2020-04-2616:30borkdudecool#2020-04-2616:31nonrecursiveclj-kondo has seriously improved my programming life 🙇#2020-04-2617:46hadilsHi! I like clj-kondo but I am having problems getting it to work with Cursive 2020.1 I followed the instructions but it still doesn't pop up the lint info when I hover. Any suggestions?#2020-04-2617:47hadilsBTW, this is an awesome tool! I work with Datomic Cloud and this will cut down on the number of deploys to get error messages.#2020-04-2617:48borkdude@hadilsabbagh18 Cool. Did you also see the datalog linting? About Cursive: hmm, I don't know, how are you using it, via the filewatchers or LSP? Did you try turning it off and on again (seriously.. ;))?#2020-04-2617:49hadilsI am using the File Watchers. I restarted several times.#2020-04-2617:49hadilsShould I try LSP instead?#2020-04-2617:50borkdudeWorth a try, but still I think it should work. Maybe @timothypratley knows something#2020-04-2617:52hadilsHi @timothypratley! I have problems using clj-kondo with Intellij Cursive 2020.1 with File Watchers. I have followed all the directions and nothing pops up when I hover over bad code. Any suggestions?#2020-04-2617:52borkdudeBut you do see the squirlies?#2020-04-2617:53hadilsI don't see anything. I know it works because I ran clj-kondo on the command line.#2020-04-2617:55borkdudeAh. Maybe a configuration error? Did you follow the instructions to the letter?#2020-04-2617:56hadilsYes. I compared the screen on Github to the one on my IDE and they match. I did all the prep work with .clj-kondo in my directory and linting the classpath.#2020-04-2617:56hadilsBut I wouldn't rule out a config error...#2020-04-2617:56borkdudeMaybe the plugin isn't activated in your Clojure file?#2020-04-2617:57borkdudeDo you also use Cursive?#2020-04-2617:57hadilsYes#2020-04-2617:57hadilsI have the Ultimate edition.#2020-04-2617:57borkdudemaybe make a screenshot of your current config? with advanced settings expanded#2020-04-2617:58hadilsI will, hold on a sec.#2020-04-2617:59hadilsMy configuration#2020-04-2618:00hadilsWorking directory is set to $FileDir$ btw.#2020-04-2618:01borkdudeLooks correct to me. Is clj-kondo on the path ?#2020-04-2618:02hadilsLet me check.#2020-04-2618:02hadilsHmm, let me restart my computer and see what happens.#2020-04-2618:03borkdudeWhat OS are you on?#2020-04-2618:09hadilsMacOS. I just restarted and put the absolute path of clj-kondo in the setup. Let me see if that works...#2020-04-2618:18hadilsSo it still doesn't work. What else should I try?#2020-04-2618:22borkdudeI'll try locally#2020-04-2618:28borkdudehmm, I can't get it to work either. Strange!#2020-04-2618:28borkdudeMaybe try the LSP alternative then#2020-04-2618:30borkdudeMaybe it's an issue with the FileWatchers plugin. Can you maybe test it with something else they claim that should work?#2020-04-2618:32hadilsOk, I'll try the LSP alternative.#2020-04-2618:32hadilsThe File Watcher was a plugin...#2020-04-2618:34borkdude?#2020-04-2618:34hadilsFor 2020.1 Ultimate -- not built in.#2020-04-2618:35hadilsI'm going to set up LSP now.#2020-04-2618:45hadilsIt's completely different on 2020.1 I will figure it out and document it.#2020-04-2618:45borkdudethanks#2020-04-2619:08hadilsSorry, I misunderstood the LSP instructions. They work now. I have clj-kondo working properly on my Intellij. No changes to docs are necessary. Thanks for your help!#2020-04-2619:09borkdudecool!#2020-04-2619:09borkdudeit's a pity that the Filewatcher is not working anymore, but gladly there is another option#2020-04-2619:59timothypratleyHi @hadilsabbagh18 I am glad you got got it working with LSP 🙂 Just FYI all I know is that 2020.1 no longer supports the FileWatchers plugin. I don’t know why and I hope if we just wait a bit longer that will be resolved. But there is not really much difference between LSP and FileWatchers, so you are probably best off just sticking with LSP 🙂#2020-04-2620:00borkdudeso it's a known issue?#2020-04-2620:00hadilsThanks for the feedback @timothypratley. LSP is working fine for me now.#2020-04-2620:07timothypratley@borkdude ah I’m a little confused to be honest 🙂 When I upgraded IntelliJ it said FileWatchers was unsupported, but now I just opened up and enabled them and they are working fine#2020-04-2620:08timothypratleyso FWIW the FileWatchers way works for me still on 2020.1#2020-04-2620:08borkdude@timothypratley I just set up filewatchers in 2019.2 but it doesn't work for me anymore, if I follow the directions#2020-04-2620:09borkdudeI'll try 2020.1#2020-04-2620:10timothypratleyCan you check that they are “enabled”?#2020-04-2620:14borkdudenow my IntellliJ is very unstable after upgrading it.#2020-04-2620:15timothypratleyuh oh 🙂 that sounds bad…#2020-04-2620:17borkdudeI had to disable Cursive, because of some crash#2020-04-2620:19borkdudeNow it should work again.#2020-04-2620:19borkdude#2020-04-2620:19borkdudebut it doesn't#2020-04-2620:20borkdudeNo warning:#2020-04-2620:22borkdudeI don't know enough about IntelliJ, I'm giving up on the FW for today, since my wife needs me now 😉#2020-04-2620:24timothypratley:thumbsup: I think tomorrow I can try out a fresh VM and experiment, no ideas right now either sorry.#2020-04-3015:52Adrian Smithhonestly the filewatchers thing feels like a bit of a hack compared to using the lsp plugin anyway#2020-04-2811:40Ian FernandezHello, how can I search a function signature that resembles my macro signature?#2020-04-2811:41Ian FernandezI've tried to lint a macro like clojure.core/def and I got warning: inline def #2020-04-2811:51borkdude@d.ian.b What does your macro look like when called?#2020-04-2811:51Ian Fernandezaw, changed to var and looks cool#2020-04-2811:52Ian Fernandezanother one that I can't find resemblance is#2020-04-2811:52Ian Fernandez(defmacro spy-on [fun-monitor-pair & body] ,,,,#2020-04-2811:53Ian Fernandez(helpers/spy-on [fn1 fn1-mon fn2 fn2-mon] (body) )#2020-04-2811:53borkdudelooks like clojure.core/let to me#2020-04-2811:53Ian Fernandeztried#2020-04-2811:54Ian Fernandez: error: unsupported binding form a-namespace/fn1#2020-04-2811:54borkdudeit seems you have not given me the example like you are calling it#2020-04-2811:54Ian Fernandezfor (helpers/spy-on [a-namespace/fn1 fn1-mon] (body) )#2020-04-2811:54Ian Fernandezsorry ^^'#2020-04-2811:55borkdudecan you try clojure.core/binding?#2020-04-2811:56Ian Fernandezerror: unresolved symbol fn1-mon#2020-04-2811:57borkdudeso where is fn1-mon coming from?#2020-04-2811:57Ian Fernandezis a name that i'm giving#2020-04-2811:57borkdudeso you have the name on the right instead of most macros which have the name on the right. that makes it incompatible#2020-04-2811:57Ian Fernandezit's like inside a macro, i'm creating an atom named of this#2020-04-2811:58Ian Fernandezyeah#2020-04-2811:58borkdudemaybe you could try changing your macro. and else: {:linters {:unresolved-symbol {:exclude [(foo.helpers/spy-on)]}}}#2020-04-2811:59borkdudeI think in your code binding should work, if you reverse names to the left#2020-04-2811:59Ian FernandezYeah, I will try this 😃#2020-04-2812:04Ian Fernandezfixed the order of macro call, clojure.core/let did the job#2020-04-2812:04Ian Fernandez😃#2020-04-2812:04Ian Fernandezthanks @borkdude#2020-04-2812:04Ian FernandezIt wasn't me that made the macro =(#2020-04-2812:08borkdudecool 🙂 preventing the Lisp curse with clj-kondo#2020-04-2910:53gordonWe're using (and loving) clj-kondo, but I was wondering if anybody has found a nice, automated, way for clj-kondo to play well with HugSQL? HugSQL defines functions at namespace load-time, and tickles the undeclared-var linter. We can declare the vars before invoking HugSQL, or we can configure clj-kondo to ignore those particular vars, but neither solution is particularly elegant, they both need manual updating if we add more HugSQL functions.#2020-04-2910:55borkdude@gordonsyme_clojurians I use hugsql and I do use declare. Another way is to just turn the unresolved symbol linter off for that namespace. Another workaround: use a small namespace foo.db.hugsql in which you let hugsql create the functions. then you require that namespace from foo.db as [foo.db.hugsql :as queries] and voila, no more warnings. you just type queries/select-users and clj-kondo won't complain anymore#2020-04-2910:56borkdudeI just thought about that last way while typing, I think I'm going to try that myself as well#2020-04-2910:58gordonThanks, that's a neat idea!#2020-04-2912:27mafcocincoWe also use HugSQL. That is a neat idea! We currently use the declare approach (which was originally suggested to me by @borkdude). It works great and, though it requires some discipline to keep in sync with the corresponding file, does have the nice side benefit of providing a .clj file where a person could look to see what functions are available without having to look through the SQL.#2020-04-2912:30mafcocincoOur namespacing is similar, which makes it very easy to navigate the code. Generally, our (Hug) .sql files are kept on a path project/sql/schema_name/table_name.sql and are then loaded by a .clj file located at project.queries.schema_name.table_name. Any namespace that needs to interact with the specified table includes the project.queries.* namespace and has all the functions they need. Has made it pretty simple (i.e. predictable) for devs to navigate the various HugSQL functions within a project.#2020-04-2919:27plinshello, Im trying to work with slingshot/try+ and Id like to know If there is a macro in clojure like
(catch [:type error/not-found] {:keys [msg]}
  ...)
so I can use lint-as
#2020-04-2919:30borkdudeI don't think there is. Probably the :unresolved-symbol config is what you need here#2020-04-2920:10plinsdid this, the warning went away, but what happens then? everything inside the try+ block is ignored?#2020-04-2920:35borkdudethe false positives because of that macro are gone, at the cost of false negatives#2020-04-2920:36borkdudeslingshot/try+ seems like a library that is used quite a lot, so I'd be happy to get built-in support for that. feel free to post an issue about it#2020-04-2920:36borkdudeI don't personally use it#2020-04-2921:42plinsok thanks Ill do that 🙂#2020-04-2921:46plinshttps://github.com/borkdude/clj-kondo/issues/874 hope its descriptive enough#2020-04-2921:47borkdudeyes, thank you#2020-04-3015:59seriogaHi @borkdude Looks like I cannot disable :unresolved-namespace linter using namespace meta.
(ns dev.playground
  {:clj-kondo/config {:linters {:unresolved-namespace {:level :off}}}})

(clojure.java.shell/sh "whoami")
> warning: Unresolved namespace clojure.java.shell. Are you missing a require? But the option works when placed in the main config.
#2020-04-3016:00borkdude@serioga I also noticed that myself and created an issue for it: https://github.com/borkdude/clj-kondo/issues/870#2020-04-3016:00borkdudeFollow up question: why would you like to turn it off?#2020-04-3016:02seriogaI have a single file for experiments in my project. So I don't want to see warnings when I check whole project.#2020-04-3016:03borkdude@serioga You can also ignore that file with clj-kondo --lint "$(clj -Spath)" --config '{:output {:include-files ["^clojure/test"] :exclude-files ["tap"]}}'#2020-04-3016:03seriogaAlso I think it would be useful to be able to specify exact namespaces to ignore. Especially those which are preloaded using profiles.clj.#2020-04-3016:04serioga> You can also ignore that file not sure I want to ignore it completely when editing 🙂#2020-04-3016:05borkdudeok, then you'll have to wait for #870 🙂#2020-04-3016:05seriogano problem 🙂#2020-04-3016:06serioga> it would be useful to be able to specify exact namespaces to ignore what do you think about this?#2020-04-3016:06borkdudeyeah, that makes sense#2020-04-3016:06borkdudepost it in another issue#2020-04-3016:07borkdudeso far I didn't need that myself yet though#2020-04-3016:07borkdudecan you give a good realistic example ?#2020-04-3016:08seriogaespecially this is annoying inside comment, where Cursive and clj-kondo cannot agree about used/unused namespace aliaces#2020-04-3016:08borkdudeyou can turn linting off in comment if you want#2020-04-3016:09serioga> can you give a good realistic example ? I'll prepare in the ticket#2020-04-3016:10serioga> turn linting off in comment also bad option, this helps to keep commented code in sync#2020-04-3016:11borkdudeyes, I prefer to keep it on as well, but personally I don't have any conflicts with unresolved namespaces in comment sections#2020-04-3016:11borkdudeso I'm curious about your example#2020-04-3016:20seriogaAlso maybe it would be useful to print linter ID with message. It's tricky to find exact configuration option from the message.#2020-04-3016:28borkdude@serioga you can also output as JSON or EDN, this will also print the name of the linter#2020-04-3016:28borkdudealso, there's a link on config.md that points to all available linters#2020-04-3016:32borkdudeMaybe there can be a setting to turn it on, I think I wouldn't like it by default#2020-04-3016:33seriogaI know about config.md. But having message "Unresolved namespace" I cannot find this text there.#2020-04-3016:33seriogaSo for me the most reliable way it to dig into source code 🙂#2020-04-3016:35serioga> you can also output as JSON or EDN and how to enable EDN output?#2020-04-3016:36seriogaah, found#2020-04-3016:39serioga> you can also output as JSON or EDN well, it's acceptable for debugging#2020-04-3016:45borkdude@serioga It is documented at the top of config.md how to find those names.#2020-04-3016:46borkdudeIt has a link to the source where all these keys are defined.#2020-04-3017:19serioga@borkdude > It is documented at the top of config.md how to find those names. Can you point me to exact text? The use-case: I see a message warning: Unresolved namespace clojure.java.shell. Are you missing a require?. How can I find corresponding linter ID from config.md or linked configuration file?#2020-04-3017:29borkdude@serioga "Look at the default configuration for all available options." There is a link in that sentence#2020-04-3017:30seriogaYes, it is liked to https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/config.clj But where is no text Unresolved namespace there!#2020-04-3017:33seriogaMy point is that I should guess linter ID from the message, but I cannot find exact text there, which is located in https://github.com/borkdude/clj-kondo/blob/36c0e7ce65521c0b7eb3a09c787ddf7e9b6d4219/src/clj_kondo/impl/linters.clj#2020-04-3017:34seriogaBut anyway I'm fine with EDN output as workaround#2020-04-3017:47borkdudeok, cool#2020-04-3019:04dominicmI suppose the first person to get their funky macro shape into kondo wins. The trick is to identify a popular macro that doesn't work in kondo with any existing vars, and then name make a library with (defmacro dominic-rules) and then add that to kondo. Then when users of the popular library add the macro alias, they will add it as popular/library dominic-rules. ;)#2020-04-3019:05borkdude🙂#2020-05-0116:31dominicmWhat's the status of carve & cljs? I have some very obviously in-use vars being highlighted by carve.#2020-05-0117:46borkdudeWhen I put this in a file foo.cljs and run carve over it:
(defn foo [])
(identity foo)
it doesn't report anything. But when I remove (identify foo) it reports foo as unused.
#2020-05-0117:46borkdudeInvoked as:
clojure -A:carve --opts '{:paths ["/tmp/foo.cljs"]}'
#2020-05-0117:47borkdudeso I can't repro what you are saying#2020-05-0116:32dominicmDoes it maybe struggle with fns used as vars?
(defn foo [] )

(identity foo)
?
#2020-05-0121:49borkdudeResponded in the other message. With this code I couldn't repro your problem. If you have another piece of code that can reproduce it, I'd be happy to take another look#2020-05-0122:13dominicmI will take a look with a real repro, thanks for going so far with it.#2020-05-0122:13dominicmI suspect it might be due to the use of foreign libs in clojurescript#2020-05-0122:14dominicmSo instead of identity, it's a function that uses a npm namespace#2020-05-0212:37dominicm@U04V15CAJ I think it's upset because I do (defonce init (mount)) to mount the application... which is unused, which then everything is transitiviely unused too...#2020-05-0212:44dominicmAdding that ns to the ignored ns seems to have sorted it!#2020-05-0212:45borkdudekewl!#2020-05-0212:46dominicm40 unused vars to clean up :)#2020-05-0210:41borkdudeclj-kondo 2020.05.02: https://github.com/borkdude/clj-kondo/releases/tag/v2020.05.02#2020-05-0214:58ChaseI'm curious on how folks update to these latest, greatest versions. Right now I delete the one in my /usr/local/bin, unzip the new one and place it in there. easy peasy but wondering if I've missed out on a simple one liner update thingy or something#2020-05-0215:00borkdude@chase-lambert what OS?#2020-05-0215:00ChaseLinux#2020-05-0215:00ChaseDebian#2020-05-0215:01borkdudeAll the options are documented here: https://github.com/borkdude/clj-kondo/blob/master/doc/install.md There is an install script as well.#2020-05-0215:01ChaseMy method works just fine but it's like on ocd thing where I have to update to the latest one when I see you post something about clj-kondo or babashka#2020-05-0215:02ChaseAhh, I missed that last line saying it will update if reran.#2020-05-0215:02borkdudeYeah, it won't check for newer versions though, it will always just fetch the latest and replace#2020-05-0215:24dominicmFeels like there's a babashka script in here somewhere...#2020-05-0215:24dominicmcronbashka#2020-05-0215:24dominicmI would suggest "Cronie" (which has nice granny connotations) but there's already a cron named that#2020-05-0215:25dominicmOh, apparently "crony" is the correct spelling anyway, which isn't taken :)#2020-05-0215:31borkdudecron?#2020-05-0215:32borkdudeYou could query the Github API for the newest version, compare that to the current version and update if necessary.#2020-05-0215:38dominicmCron would make it an automatic once a day update or something.#2020-05-0218:07skykaninMight not be the right place to ask, but I'm having issues installing clj-kondo through Nix. For some reason it's trying to building graalvm 19.2.1 from scratch and failing. https://discourse.nixos.org/t/issue-building-graalvm-19-2-1-dependency-for-the-clj-kondo-package/6932#2020-05-0218:10borkdudeYeah, sorry, I don't now anything about nixOS, but you could try to read through the issues and contact the person who made support for that#2020-05-0220:03skykaninyeah ok, the graalvm package is borked. Thanks anyways#2020-05-0220:06borkdudeyou could try to upgrade to 19.3.1 which is what clj-kondo is using nowadays#2020-05-0411:52yendais there a way to exclude private-vars from the linting? I only found how to exclude unused private vars#2020-05-0412:54borkdude@yenda search the issues for private - I have some docs in an issue #2020-05-0412:55borkdudeCan’t give you the link - afk#2020-05-0413:16yendathanks found it#2020-05-0513:22dominicmsuggestion:
(let [foo 10
      _ (side-effect!)]
  ...)
to be
(let [foo 10]
  (side-effect!))
#2020-05-0513:22dominicmtail position of let shouldn't be used for side effects, only for inbetween options.#2020-05-0514:15gerred@seancorfield don't I owe you something on linter-kondo?#2020-05-0515:06seancorfield@gerred Yup. To add support for :info level responses.#2020-05-0515:17gerredohh yes#2020-05-0515:17gerredI'll do it this week, sorry, busy past few weeks.#2020-05-0515:50seancorfieldNo rush! Changing a couple of linters to run at :info level instead of :warning is fairly far down my list 🙂#2020-05-0600:49fiddlerwoaroofIs there an exclusion list for unused imports?
#2020-05-0600:51fiddlerwoaroofAlso, was there a way to use Clojure metadata to configure clj-kondo?#2020-05-0601:05seancorfield@fiddlerwoaroof You can provide metadata on the ns form for per-file configuration overrides.#2020-05-0601:05seancorfield
(ns worldsingles.expectations.mobile.user
  {:clj-kondo/config
   '{:lint-as
     {worldsingles.expectations.mobile.user/patch-notifications
      clj-kondo.lint-as/def-catch-all}}}
  (:require [clj-time.coerce :as tc]
            [clj-time.core :as t]
            [clj-time.format :as tf]
...
#2020-05-0601:05seancorfieldNote the ' so the symbol names do not get evaluated!#2020-05-0601:06fiddlerwoaroofThanks, I really dislike the friction a separate config file adds#2020-05-0601:06seancorfield(metadata on ns can come before the namespace name if you use ^)#2020-05-0601:07seancorfieldI have a config file in each project, at this point, with just that one override so far.#2020-05-0601:07fiddlerwoaroofMy current issue is that I have to import a JDBC driver, but I never use it directly and I can't figure out how to hide the warning#2020-05-0601:07seancorfieldReally? Why is that?#2020-05-0601:07fiddlerwoaroofBecause it's used implicitly when the connection string is parsed#2020-05-0601:08fiddlerwoaroofHmm, maybe I don't need the import#2020-05-0601:08seancorfieldNeither clojure.java.jdbc nor next.jdbc need you to import the JDBC drivers.#2020-05-0601:08fiddlerwoaroofCool, I wasn't thinking things through#2020-05-0601:08seancorfieldFixed your warning for you! 😆#2020-05-0616:05fiddlerwoaroofthanks#2020-05-0620:37lreadHeya @borkdude! I am slowly dipping my toes back into rewrite-cljc. It has been a long while since I spent time with my old reliable and helpful clj-kondo. I have missed her and the reunion is delightful. I noticed 2 small things while updating to the latest clj-kondo (remember I have been away for literally months!): 1. clj-kondo --help does not show cljc as a valid option for --lang, should it? 2. I had to add "<stdin>" to my clj-kondo .config.edn->`:output` -> :include-files to get spacemacs to show clj-kondos findings. I now have :output {:include-files ["<stdin>" "^src" "^test" "^script"]}. If having to include <stdin> is by design, a note in the docs might be helpful. Am happy to make PRs for above if there is any work to do.#2020-05-0620:41borkdude@lee 1) Yeah, it should. 2) Why are you excluding test files from linting in your editor? Clj-kondo is pretty helpful there too. Scripts: dunno. Maybe just try without the entire include-files thing and start over?#2020-05-0620:55lreadFor 2) I have a single clj-kondo config to support CI scripts and my editor. My CI script runs clj-kondo with my project classpath but I only want to see clj-kondo warnings from my project sources. You helped me come up with this solution in the very early days, but that was long ago and maybe there is a better way.#2020-05-0620:56borkdude@lee In CI you can add the --config flag to pass additional config, they will be merged#2020-05-0620:56lreadah… ok, thanks will give that a go.#2020-05-0621:07lreadya that works great, thanks @borkdude! simple_smile#2020-05-0621:09borkdude😄#2020-05-0620:53yonatanelHi, I’ve made a try-let abomination macro that needs to be linted as both a let and a try block. How can I configure it? Usage:
(try-let [a (db-connection)
          b (might-throw)]
  (process a b)
  (catch Exception e
    (when a (close a))
    (when b (close b))
    (throw e)))
#2020-05-0621:04borkdudeyou can turn off linting with :unresolved-symbol {:exclude [(weird.macros/try-let)]}#2020-05-0621:53yonatanelIs it possible to extend the analyzer instead with a custom analyzer? I scanned the source briefly and I can’t find a way?#2020-05-0621:54borkdudenot at the moment#2020-05-0622:00seancorfield@yonatanel It won't help you but my opinion, after spending a bunch of time trying to get clj-kondo to "like" some of my macro-based code, is that it's a really good idea to make sure you don't create new syntax via macros that doesn't "match" something that is in Clojure already 🙂 It's made it clear to me just how hard it would be for someone new to my code to be able to read stuff that uses macros that have "unexpected" syntax. I'm seriously rethinking some of the syntax in my Expectations library at this point, after wrestling with clj-kondo!#2020-05-0622:03yonatanelTrue, we get carried away sometimes.#2020-05-0709:13practicalli-johnFirst rule of macro club, don't create macro's (unless there is an extremely compelling reason)#2020-05-0710:24Marc O'MorainI’m getting tempted to implement macro-expansion in clj-kondo 🙂#2020-05-0712:27bherrmannI thought I'd try using clj-kondo with emacs. So I think I followed the instructions... but I'm not getting rightly harassed by the checker...#2020-05-0712:27bherrmann#2020-05-0712:33delaguardoyou have disabled flycheck clj-kondo is working together with flychek#2020-05-0712:27bherrmannI presume it should be giving me feedback about the select-keys statement.#2020-05-0712:33bherrmannHumm..... (flycheck-buffer) says "Flycheck mode diabled"#2020-05-0712:36bherrmann
evaling this turned it on ...  (global-flycheck-mode)
#2020-05-0716:13hindolYou should not turn it on globally though. You should hook it with the Clojure mode you are using.#2020-05-0716:14hindolUnless you wanted to turn on flycheck mode for every major mode.#2020-05-0719:02bringeHello, I'm trying to exclude a couple of macro symbols from being linted. This is my config in .clj-kondo/config.edn in the root of my project (same level as deps.edn).
{:linters 
 {:unresolved-symbols 
  {:exclude [(io.pedestal.interceptor.error/error-dispatch [ctx ex])]}}}
Then in my code I require this namespace/function like
[io.pedestal.interceptor.error :refer [error-dispatch]]
But ctx and ex are still getting flagged as unresolved
#2020-05-0719:02bringe#2020-05-0719:02bringeI am pretty sure I'm doing something wrong, but not seeing what#2020-05-0719:03borkdudeWithout a minimal but complete repro I also can't see what 🙂#2020-05-0719:05borkdudeAh, spotted it#2020-05-0719:05borkdudethe linter is called *-symbol single, not plural#2020-05-0719:05borkdudesingular#2020-05-0719:07bringeAh thanks!#2020-05-0722:32just.sultanovHello everyone! Is it just that I can’t download the latest release? Or does everyone have a problem? https://github.com/borkdude/clj-kondo/releases/download/v2020.05.02/clj-kondo-2020.05.02-linux-amd64.zip#2020-05-0722:33borkdudeit seems to be a general Github problem. babashka builds are failing to because of this#2020-05-0722:35just.sultanovOh 🙂 I thought so. Also encountered a problem on the CI#2020-05-0722:45nateseems to be fixed now#2020-05-0722:45nateI can download from github again#2020-05-0723:17just.sultanovMe too. Thanks, @nate #2020-05-0802:17wilkerluciohello, I'm getting this error on a project:
Unexpected error. Please report an issue.
java.lang.IllegalArgumentException: /scrollparent.transit.json is not a relative path
        at $as_relative_path.invokeStatic(io.clj:414)
        at $file.invokeStatic(io.clj:426)
        at $file.invoke(io.clj:418)
Ideas on what may be going on?
#2020-05-0802:18seancorfieldIs that perhaps part of a top-level def that has side-effect-y stuff in it? (hard to tell without more of the stacktrace)#2020-05-0802:21wilkerlucioafter some debugging I found the issue is when you have a :require on cljs that uses a root link, eg: (:require ["/something" :as js-local-thing])#2020-05-0802:22wilkerluciowhen I replaced with ../something it works#2020-05-0802:30seancorfieldOh wow... I didn't know paths were a thing in cljs requires!#2020-05-0806:19orestisThey’re not, that’s a shadow-CLJS thing. #2020-05-0806:19orestis(I think!)#2020-05-0803:42wilkerlucioanother thing that I'm having, when I run clj-kondo --lint src on my project, its not reporting unsorted namespaces, but when I save the file from my editor and it triggers from that, the error is reported, both using same config, is there something I'm missing here?#2020-05-0804:39wilkerlucioand funny enough, when I run in the CI it triggers the errors for unsorted namespaces :man-shrugging:#2020-05-0805:19wilkerlucioon this, its not just the unsorted imports, some redundant do also did show up on CI, but not on my machine via clj-kondo --lint src, but those also show in my editor when I save a file#2020-05-0805:08wilkerlucioand still about unsorted imports, currently clj-kondo is sorting based on the real ns name, not in what is written, so when we have string requires from cljs, its working as if they were symbols (and expecting them to be in the middle), but I like that JS imports (from strings) appear at the top, also sorting libs like ns-org will also put the strings first, @borkdude do you think we can make this setting configurable, so I can choose to have the string requires at top?#2020-05-0805:12wilkerlucioexample:
; this is what I consider organized
(ns devcards.render
  (:require
    ["react" :as react]
    [devcards.util :as d-u]
    [reagent.core :as r]
    [relemma.util :as u]))

; this is what clj-kondo considers organized
(ns devcards.render
  (:require
    [devcards.util :as d-u]
    ["react" :as react]
    [reagent.core :as r]
    [relemma.util :as u]))
#2020-05-0806:38borkdude@wilkerlucio please upgrade, you are using and old version. The local path require issue has been fixed. Also the issue about str/replace you posted on Github#2020-05-0806:39wilkerluciooh, cool! @borkdude I did the install yesterday from homebrew, maybe the recipe there is not on latest?#2020-05-0806:40borkdudeCan you repeat the version you have?#2020-05-0806:41wilkerlucioclj-kondo v2020.01.13#2020-05-0806:42borkdude@wilkerlucio How did you install. From which brew thing? https://github.com/borkdude/homebrew-brew/blob/master/clj-kondo.rb borkdude/brew/clj-kondo 2020.02.15 -> 2020.05.02 ==> Upgrading borkdude/brew/clj-kondo 2020.02.15 -> 2020.05.02#2020-05-0806:43wilkerlucioI think I followed the instructions, but maybe I just did brew install clj-kondo#2020-05-0806:44borkdudehmm, does brew have clj-kondo in the official repo now maybe...#2020-05-0806:45borkdudeI don't think so. Maybe your issue was the issue that Github had yesterday. Can you uninstall it and do it over?#2020-05-0806:45borkdude
brew install borkdude/brew/clj-kondo
#2020-05-0806:48wilkerlucio@borkdude just figured out my problem, in the project that Im working there was already a clj-kondo install from NPM, and when I was running from that folder was picking that instead of the system installation facepalm#2020-05-0806:49borkdudemakes sense 🙂#2020-05-0806:49wilkerluciobut about the local path thing, clj-kondo still complains about bad ordering when string requires are on top#2020-05-0806:50wilkerluciothis is getting me a lint error:
(ns devcards.render
  (:require-macros
    [devcards.core :refer [defcard]])
  (:require
    ["react" :as react]
    [devcards.util :as d-u]
    [reagent.core :as r]
    [relemma.util :as u]))
#2020-05-0806:50wilkerlucioI need to change some config?#2020-05-0806:50borkdudeabout the sorting: don't know - David Nolen told me that strings are allowed in require only to support things that you can't express using symbols. In that sense they are no different. But clj-kondo does treats string requires as JS library requires, so you can use the namespace objects. I don't think it should affect the sorting.#2020-05-0806:50borkdudeE.g. you can do (:require ["clojure.set" :as set]), it's valid in CLJS#2020-05-0806:51borkdudeMaybe putting them in separate (:require ...) clauses helps#2020-05-0806:51wilkerlucioyeah, but would be nice if clj-kondo could respect the pure string checking there, I because tools like nsorg will put those first#2020-05-0806:52wilkerlucioalso, I like that the separation gets clear about what is JS and what is CLJ (altough is purely a convention)#2020-05-0806:52wilkerluciodo you think its hard to support that? I wonder if clj-kondo currenty can tell the difference, I would be willing to work on that if you think its a feasable (and you want the feature :))#2020-05-0806:53borkdudeone problem is that different editors might have different opinions on sorting. if you can verify that e.g. Emacs / clojure-mode does the same thing for string requires, Atom, VSCode, etc, then it might start to make sense. But right now I'm not so certain of that.#2020-05-0806:53wilkerlucioI'm thinking of adding this as a configurable thing#2020-05-0806:53borkdude@wilkerlucio Have you tried a separate require?#2020-05-0806:54borkdude
(:require ["foo.js"])
(:require [clojure.set :as set])
#2020-05-0806:54wilkerluciooh man, I would rather not if possible, thats hundreds of files to change 😛#2020-05-0806:54borkdudewell, you can make an issue and then I'll for one check what emacs does#2020-05-0806:55borkdudewhat editor are you using?#2020-05-0806:55wilkerluciowould you be willing to take it if was a configurable feature? like :unsorted-required-namespaces {:level :warning :strings-first? true}#2020-05-0806:55wilkerlucioI'm on IntelliJ#2020-05-0806:56wilkerlucionsorg is a separated tool I run from lein, that sorts all namespaces#2020-05-0806:56borkdudeThe right order is: issue, hammock time/discussion, then PR. Maybe @helios also has an opinion on this, he created that linter.#2020-05-0806:56borkdudeMention nsorg in the issue#2020-05-0806:57wilkerluciosure, just checking if it something you thing its interesting to consider#2020-05-0806:57wilkerluciodo you know if the information about the original definition (if its a string or a symbol) is available at the linter call for this?#2020-05-0806:57borkdudeyes, we save that information#2020-05-0806:58wilkerluciocool 🙂 gonna open the issue for discussion#2020-05-0807:05wilkerluciohttps://github.com/borkdude/clj-kondo/issues/885#2020-05-0807:05wilkerluciohttps://github.com/borkdude/clj-kondo/issues/885#2020-05-0807:07thumbnailHey 👋:skin-tone-2: , I’m trying to setup the LSP server in InteliJ, but i get timeouts (see screenshot). Also manually running java -jar ~/bin/clj-kondo-lsp-server-2020.05.02-standalone.jar yields nothing on openjdk 1.8.0_232 . How would i go about debugging this 😬 I also tried 2020.04.05#2020-05-0807:08wilkerlucioI didn't tried that, but the setup with FileWatchers worked very well here on IntelliJ#2020-05-0807:09thumbnailThe filewatcher setup is working correctly indeed, but i was intrigued for the lsp impl for a personal project 😬#2020-05-0807:10borkdudeIt's funny because recently there was the exact opposite conversation: nobody could make the filewatchers work, so LSP was preferred 😉#2020-05-0807:11borkdude@UHJH8MG6S You can enable logging in the LSP plugin#2020-05-0807:11borkdudeso inspect the log file#2020-05-0807:13thumbnail🎉 It needs an absolute path#2020-05-0807:13thumbnailIt works now, thanks. the log showed it couldn’t find the relative path#2020-05-0807:13borkdudeah the tilde is probably not expanded#2020-05-0807:13thumbnailexactly#2020-05-0809:05jeroenvandijkHi I’m pretty new to clj-kondo and specifically using it for a Clojurescript project. For now I’ve copied the setup of clj-kondo itself. If anyone wants to give feedback on this pull request that would be very much appreciated https://github.com/athensresearch/athens/pull/38 It’s also for a good cause (an opensource tool for open knowledge)😎#2020-05-0818:23borkdudeHi Jeroen. Using the config from clj-kondo itself doesn't make much sense to me as that is used for linting clj-kondo itself. I would just start with a clean slate and add config when needed#2020-05-0818:41jeroenvandijkThanks Michiel :)#2020-05-0818:42borkdudeAll options are documented here: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#2020-05-0912:49jeroenvandijkecht heel tof die pods. En met jvm helemaal precies wat ik nodig heb straks voor bijvoorbeeld die filewatcher#2020-05-0912:50jeroenvandijkzag dat je emailadres publiek staat op je github (ook als je niet ingelogd bent). Weet niet of dat je bedoeling was#2020-05-0918:05borkdudekan op zich geen kwaad denk ik toch?#2020-05-0918:06borkdudespamfilter van gmail is goed 😉#2020-05-0815:14seriogaCLJS does not support multiple requires 😞 https://clojurians.slack.com/archives/CHY97NXE2/p1588920691162900#2020-05-0818:24borkdude@wilkerlucio Now I remember: for reader conditionals we just ignored the clauses with respect to sorting. Would that also be good for string requires?#2020-05-0818:39wilkerluciothat's a interesting question, I can't remember a time that I used string requires on .cljc, but I see this example in Fulcro: https://github.com/fulcrologic/fulcro/blob/bdb34022d0d51e150b3a3ee1e45a7cdc5ebdea2b/src/main/com/fulcrologic/fulcro/routing/legacy_ui_routers.cljc#L1-L17#2020-05-0818:40borkdudeNo, I mean: ignore string requires with regards to sorting like we do with reader conditionals, not the combination of those two#2020-05-0818:40wilkerlucioso, IMO, I like the #? itself to be ignored, but if possible, check the sorting inside, having sam the string consideration (please note this example of fulcro is not actually sorted, but the strings are on top)'#2020-05-0818:41borkdudeclj-kondo ignores reader conditionals for sorting because the order in which tooling sorts your ns requires is quite undefined#2020-05-0818:42borkdudewe can do the same with strings#2020-05-0818:42wilkerluciooh, ignore could be an option, feels like group, but if possible I would like better to have the option to enforce it#2020-05-0818:43wilkerlucioits so awesome to have kondo on the pipeline getting those 🙂#2020-05-0818:45wilkerluciodo you have concerns about adding this complexity to the lint?#2020-05-0818:47borkdudeI'm more concerned with adding config that's only useful to one person while the second person needs something slightly different and there will be another option#2020-05-0818:47borkdudeI just tested this in emacs and clojure-mode also sorts string requires on top#2020-05-0818:47borkdudeso it might make sense just to make this the default sorting#2020-05-0818:47borkdudewithout another option#2020-05-0818:47borkdudeI'll add that to the issue#2020-05-0818:49wilkerluciooh, sgtm, I wonder if I'm the first trying to use it with cljs like this (or first talking about it with you :P), or if other people are sorting into the current kondo way#2020-05-0818:49borkdudethe sorting linter is optional, so there might not be a lot of people using it?#2020-05-0818:49borkdudeI mean, it's turned off by default#2020-05-0818:50wilkerlucioyeah, defaults make a difference for sure#2020-05-0818:52wilkerlucioand thanks again for the tool, I had a nice surprise when I see that the notifications got highlighted inline on the editor in intellij, every file watcher extension that I used in the past just did a external read-only console, kudos on that#2020-05-0818:54wilkerlucioone idea in my mind, do you think makes sense to use clj-kondo as a base for writing a code formatter? I played with SCI and read a bit on edamame, but I'm not sure for a code formatter which would be make more sense, if any#2020-05-0819:00borkdudeI recently found this one: https://github.com/greglook/cljstyle#2020-05-0819:01borkdudedidn't try it#2020-05-0819:22wilkerlucionice, I didn't knew about this one, thanks for the hint#2020-05-0819:25borkdudeit's also built on rewrite-clj like clj-kondo#2020-05-0821:25wilkerlucioI'm enjoying cljstyle, but one thing though, they sort the namespaces in the way clj-kondo expects -.-#2020-05-0821:26borkdudeaaargh#2020-05-0821:26borkdudeso it might be better to just ignore them with regards to sorting, so there won't be any tooling conflicts#2020-05-0821:30borkdudeor make a PR to cljstyle 😉#2020-05-0821:30borkdudemaybe he just was inspired by clj-kondo currently handles it.#2020-05-0821:30borkdudesince he has a .clj-kondo directory#2020-05-0821:30borkdudeit might be good to reach out to him#2020-05-0821:31borkdudeand also keep me up to date about what he says#2020-05-0821:59wilkerlucioyeah, I'm down to send a PR there#2020-05-0821:59wilkerlucionot nescessary for this case, but is it possible to have custom linters on my own source path and make kondo use them?#2020-05-0822:00borkdudenot at the moment. note that a typical use of clj-kondo is via the binary and that's pretty much a closed world#2020-05-0822:01borkdudeunless we involve sci into the equation#2020-05-0822:40wilkerluciohttps://github.com/greglook/cljstyle/pull/45#2020-05-0912:10yendaIt seems like the linter config :unresolved-namespace {:exclude [System]} doesn't work. I still get warning: Unresolved namespace System. Are you missing a require? in a cljc file within a defmacro#2020-05-0912:12borkdude@yenda You should wrap that part in :clj#2020-05-0917:49yendaok thanks#2020-05-1208:14flowthingIs there a way to prevent clj-kondo from warning about clojure.data.xml/alias-uri (https://github.com/clojure/data.xml/blob/04db68059e1f4ba3b07ee153cb1a73175ede51cd/README.md#namespace-support)? I've tried adding {:lint-as {clojure.data.xml/alias-uri clojure.core/alias}}, but that doesn't seem to work.#2020-05-1208:39borkdude@flowthing Can you try:
:clj-kondo/config '{:linters {:unresolved-namespace {:exclude [foo]}}}
?
#2020-05-1208:43flowthingThat works — thank you!#2020-05-1208:40borkdudeThis should be supported since the newest clj-kondo#2020-05-1218:01plinsis there support fore core.match? right now
(into [name]
                       (match [from-to-state]
                         [(:or [nil _]
                               [:installed (:or :forbidden :uninstalled)]
fails
#2020-05-1218:34borkdudethere is not (yet)#2020-05-1219:21plinsok thanks 🙂#2020-05-1421:49gerredthis weekend I'm cracking my knuckles and getting linter-kondo up to date and adding in warnings as a linter class in atom.#2020-05-1421:51borkdude@gerred cool! I think @seancorfield asked for something around info but I don't recall the details#2020-05-1421:51borkdudeinfo is a supported level in flycheck / emacs but it might not be supported in your plugin yet#2020-05-1421:56gerredidk I'm going off of the base linter, so I'll dig in and see what I can fix up there.#2020-05-1500:05vinnyataide
:syntax-quote node expects 1 value.clj-kondo
what does this mean? this is the line
#(comp/transact! this `[(bump-number {})])
#2020-05-1500:05vinnyataidethe code works correctly#2020-05-1507:19borkdude@vinnyataide I need a full repro like:
(require '[foo :as comp])
(let [this 1]
  #(comp/transact! this `[(bump-number {})]))
Btw, that full repro works fine with clj-kondo. What version are you using?
#2020-05-1523:26vinnyataidenow it fixed itself =x when I opened the project again#2020-05-1523:27vinnyataidebut vscode is always focusing on the output tab even tho it's not showing anything meaningful#2020-05-1523:27vinnyataide#2020-05-1523:28vinnyataidethis always happens when I save a file, even though I'm in the terminal tab#2020-05-1523:28vinnyataidewindows machine#2020-05-1616:01gerredI'm trying to get the right config.edn for a pedestal macro defroutes#2020-05-1616:01gerred#2020-05-1616:03gerred#2020-05-1616:03gerredgives me an unsatisfying [Error - 12:03:11 PM]  error#2020-05-1616:19borkdude@gerred
(ns foo
  {:clj-kondo/config '{:linters
                       {:unresolved-symbol
                        {:exclude [(io.pedestal.http.route.definition/defroutes)]}}}}
  (:require [io.pedestal.http.route.definition :refer [defroutes]]))

(defroutes x)
#2020-05-1616:19gerredah ha.#2020-05-1616:19gerredthank you!#2020-05-1616:19borkdudebtw, I don't know this macro, but if it's similar to compojure/defroutes, you could try lint-as#2020-05-1616:20borkdudebecause there is built-in support for compojure#2020-05-1616:20borkdudebut I bet it isn't#2020-05-1616:20gerredyeah pedestal takes a different structure#2020-05-1616:48vinnyataide@gerred still showing the unsatisfying error here#2020-05-1617:06gerredreally? it's working for me now. I did have to (declare routes) to make my var quote work#2020-05-1617:15Kari MarttilaI was reading some old posts and I understood that LSP is the preferred method to configure clj-kondo with IntelliJ IDEA (and not File Watcher)?#2020-05-1618:03didibusClj-kondo does not work in ClojureScript correct?#2020-05-1618:03didibusIf you wanted say a browser editor to support some of its linting?#2020-05-1618:04borkdude@kari.marttila just choose the one that works#2020-05-1619:09Kari MarttilaThanks! clj-kondo is a great tool - very popular at Metosin.#2020-05-1619:11borkdudeThanks!#2020-05-1618:04borkdude@didibus clj-kondo is JVM only#2020-05-1618:04didibusOk thx#2020-05-1618:05borkdude@didibus however, I made this: https://clj-kondo.michielborkent.nl/ - it's calling clj-kondo as a service#2020-05-1618:06didibusHum, ya I guess that can be an option. I was hoping to have a static website for this though, no server involved.#2020-05-1618:06didibusNow just waiting for GraalVM to have a native WASM target 😋#2020-05-1618:23bhaim123Hi Guys I'm facing an issue that maybe you already had. I have the same macro, defined in several project in different name spaces (I know it is bad, but this is the current state). (the macro is the if-let* so you can said it should be identified like the let macro). I'm trying to have one "global" config for all the projects. Not sure how to do this, was thinking about the lint-at section, but since the location of the macro in each project is different, I'm not sure it is possible. Any idea?#2020-05-1618:42borkdude@bhaim123 you can just put multiple lint-as entries for each different namespace?#2020-05-1618:44bhaim123@borkdude thanks for helping! I prefer not to do that since we have many different project and it will make the config really ugly 🙂#2020-05-1618:45borkdudethen use a different config for each project. I don't see anything in between those approaches#2020-05-1618:45bhaim123👍#2020-05-1809:33eskosRather wild idea, what if it would be possible to provide clj-kondo config fragments within JAR, eg. through symbol metadata? I also happen to have if-let* in my project(s) and for all intents and purposes it could be linted as let macro as is.#2020-05-1809:37borkdudeThat idea has come up more often and there were some problems associated with it. Can't remember the details, but feel free to look through the issues#2020-05-1812:03eskosHmm, couldn’t find any on cursory look…#2020-05-1812:05borkdude@suomi.esko https://github.com/borkdude/clj-kondo/issues/559#issuecomment-547031815#2020-05-1812:08borkdudeSo far the lowest friction solution is to just provide some docs around how to use your macro with clj-kondo. Possibly in the docstring, or in the README.#2020-05-1812:16eskosHmm, not sure if I see that as a problem. I was thinking that if I were to eg. (defmacro ^{:kondo/lint-as #'clojure.core/binding} if-let* …) that would be a pretty clean way to provide library author intended linting rule for the macro which is pulled in when the macro is used and this metadata would be taken into consideration only if project/user specific rules do not match. Not quite a huge side step IMHO but I don’t know much about how kondo works internally so maybe the issue really is there…?#2020-05-1812:22borkdudeIt's technically all possible, but too fragile imo. I mentioned already some reasons in the linked issue, I'm not going to repeat them all. clj-kondo focuses on performance. it doesn't do multi-pass linting. if someone uses a macro in code before the config metadata has been read, they will still get an error. also config would be hard to debug if library authors put invalid configs on their metadata, etc.#2020-05-1812:25borkdudealso there are several alternatives to consider how to go about this#2020-05-1812:25borkdudeit's not clear cut#2020-05-1812:26borkdudethere could be a user provided tool which scans vars for :clj-kondo/lint-as metadata at runtime and spits out that config to .clj-kondo/config.edn#2020-05-1812:26borkdudethen clj-kondo wouldn't have to support anything other than it does right now#2020-05-1812:31borkdudeFeel free to post another issue about this, and enumerate all possibilities#2020-05-1812:31borkdudeThe original issue is not easy to find and it a bit cluttered.#2020-05-1813:41borkdude@suomi.esko The problem is very similar to: why does Clojure choose to define data reader config in data_readers.clj instead of metadata.#2020-05-1813:44eskosWell, I’ll take your word for it 🙂 I don’t think I know enough to have a fully educated suggestion for this.#2020-05-2114:49dominicmI have a custom macro! I don't suppose there's something for a try variant already? I use pattern matching instead of a binding so you do this:
(try+
  (catch {:a ?a} (prn ?a)
  (catch Some.Class.Extending.IExceptionInfo {:b ?b} (prn ?b)))
I'm using meander for the binding - which I appreciate kondo won't support at least for a while. I was hoping I could do something to alleviate the pain though, as constrained as possible.
#2020-05-2114:54borkdude@dominicm not really I'm afraid, except for disabling unresolved symbols etc in this macro#2020-05-2114:54dominicmWould it be possible to mark things unresolved only in catch?#2020-05-2115:40borkdudedon't think so, because it's not really a var, more like a macro local thing#2020-05-2115:43borkdudeunless you do something like :require [my.terrific.macro :refer [catch]]#2020-05-2116:40dominicmNope :(#2020-05-2116:50dominicmI'll have to get my library very popular so I can pr it :)#2020-05-2209:30teawaterwirewhat's the proper way to remove this warning? exclude symbol or exclude namespace?#2020-05-2209:32borkdudedoes goog/isObject also work?#2020-05-2209:36teawaterwirethat works!#2020-05-2209:37teawaterwireso closure namespaces can be used that way to avoid warnings?#2020-05-2209:38borkdudethink so yes?#2020-05-2209:43teawaterwiresweet 🙌#2020-05-2209:34borkdude@teawaterwire ^ else you can add it to exclude symbol. proper fix would be something like this commit: https://github.com/borkdude/clj-kondo/commit/33cd7fd0493462e1eb0533a666b620d9a04da162#2020-05-2218:53plinsis there a way to install carve as a dev dependency using lein?#2020-05-2218:58borkdudecurrently there isn't. any reason not to use clojure?#2020-05-2219:09borkdude@plins I investigated and I can't make a Clojars release right now because I have a dependency on @lee's rewrite-cljc which is currently only git. Maybe you can try with https://github.com/reifyhealth/lein-git-down#2020-05-2219:12lreadinteresting, did not know of that clojars limitation#2020-05-2219:13borkdudeit's like that with Rust's cargo as well, you can't depend on git deps when you want to publish to their http://crates.io website. Although in the case of Clojars it might just be historical.#2020-05-2219:16borkdudeit's probably a sane default which makes things less brittle in case people remove repos etc.#2020-05-2220:18lreadyeah, that makes sense to me#2020-05-2313:58borkdudeApplied for a "Summer of Bugs" grant to get this clj-kondo issue fixed: https://github.com/borkdude/clj-kondo/issues/536 If you're using Rum, consider upvoting the isssue by giving it a thumbs up.#2020-05-2415:12nmkipI'm getting an error that says unresolved symbol merge identity In my .clj-kondo/config.edn I added this:
{:lint-as {clojure.test.check.properties/for-all clojure.core/let
           clojure.test.check.clojure-test/defspec clj-kondo.lint-as/def-catch-all}}
Am I missing something?
#2020-05-2415:13borkdudecan you also provide the namespace form? this way I can verify if you made the right config#2020-05-2415:14nmkip
(ns properties-playground.test-check.merge-test
  (:require [clojure.test :refer :all]
            [clojure.test.check.clojure-test :refer [defspec]]
            [clojure.test.check.properties :as prop]
            [clojure.test.check.generators :as gen]))
#2020-05-2415:17borkdude@juan.ignacio848 This does not give any unresolved symbols for me:
(ns properties-playground.test-check.merge-test
  {:clj-kondo/config '{:lint-as {clojure.test.check.clojure-test/defspec clj-kondo.lint-as/def-catch-all}}}
  (:require [clojure.test :refer :all]
            [clojure.test.check.clojure-test :refer [defspec]]
            [clojure.test.check.properties :as prop]
            [clojure.test.check.generators :as gen]))

(defspec merge-identity
  (prop/for-all [m1 (gen/map gen/keyword gen/small-integer)]
                (= m1
                   (merge m1 {})
                   (merge {} m1))))
#2020-05-2415:18nmkipThe map you added in the namespace form is equivalent to having the config.edn?#2020-05-2415:18borkdudeyes#2020-05-2415:19borkdudewhat version of clj-kondo are you using?#2020-05-2415:19nmkipdef-catch-all is something new? I don't remember when was the last time I updated clj-kondo 🙂#2020-05-2415:19borkdudejust upgrade, then try again#2020-05-2415:20nmkipv2019.11.23#2020-05-2415:21nmkipIt's probably that 🙂 I'll try#2020-05-2415:22nmkiphttps://github.com/borkdude/clj-kondo/releases/tag/v2020.01.10 --> def-catch-all#2020-05-2415:23borkdudebtw you can also try clojure.core/def for better linting. the catch-all is a last resort really#2020-05-2415:23borkdudeprop/for-all can be linted like let like you already had#2020-05-2415:24nmkip
[
#2020-05-2415:24nmkipOhh, my auto-completion didn't recommended me clojure.core/def, it was my first attempt though#2020-05-2415:25nmkiphowever there's also another arity for defspec#2020-05-2415:26nmkipwhich I'm not using so I will change it to clojure.core/def#2020-05-2415:26borkdudeit does seem to work:
(ns properties-playground.test-check.merge-test
  {:clj-kondo/config '{:lint-as {clojure.test.check.clojure-test/defspec clojure.core/def
                                 clojure.test.check.properties/for-all clojure.core/let}}}
  (:require [clojure.test :refer :all]
            [clojure.test.check.clojure-test :refer [defspec]]
            [clojure.test.check.properties :as prop]
            [clojure.test.check.generators :as gen]))

(defspec merge-identity 100
  (prop/for-all [m1 (gen/map gen/keyword gen/small-integer)]
                (= m1
                   (merge m1 {})
                   (merge {} m1))))
#2020-05-2415:27borkdudeThis is probably a lack of clojure.core/def syntax checking that works out nice for this use case. Might break in the future if syntax checking improves 😉#2020-05-2415:28nmkipYes, it works 😄#2020-05-2415:29nmkipThanks!#2020-05-2604:01tatutclj-kondo doesn’t yet know about npm requires and :as
% echo "(ns foo (:require [some-npm-module :as x])) (aget x \"default\")" | clj-kondo --lint -
<stdin>:1:20: warning: namespace some-npm-module is required but never used
<stdin>:1:51: error: unresolved symbol x
the x name is valid in cljs and is the npm module object
#2020-05-2606:52borkdude@tatut if you will use a string for the name it will treat it as an NPM require #2020-05-2606:53tatut:thumbsup: I’ll try that#2020-05-2620:35plinsis there a preferred way of parsing cli arguments? lets say run $ ./my-bb-script.clj --foo bar --x y , is there and a symbol like *`command-line-args*` that would hold a map of args in babashka?#2020-05-2620:37tanzoniteblackis this a clj-kondo specific question, or just a generic clojure question?#2020-05-2620:38borkdudebabashka quetions can be posted in #babashka#2020-05-2810:58eskos@borkdude Our build just broke because clj-kondo was bumped and the new :refer :all warning that I requested a while back was emitted. I absolutely love this! 😄#2020-05-2915:41wilkerluciohello, I got in a situation here that I'm not sure how to get out, considering this code:
(let [init-link-events (mapv (fn [cid]
                                    [::command-init-link
                                     {::client-id cid}]) (range clients))]
       (gen/let [chain-size    (gen-chain-size env)
                 command-chain (gen-command (-> env
                                                (assoc ::chain-size chain-size)
                                                #_(update ::command-pool into init-link-events)))]
         (into init-link-events (chain->list command-chain))))
Kondo thinks there is a redundant let here, but its not really, I understand that for kondo they are just 2 lets, is there a way to avoid this problem?
#2020-05-2915:41wilkerluciogen/let vs let#2020-05-2915:42wilkerlucioand in my setup gen/let is configured to be resolved as let#2020-05-2915:43borkdudehmm, I think we need to tweak the code to disregard things that are linted as let, but are not really clojure.core/lets#2020-05-2915:46borkdude@wilkerlucio a workaround for now would be to lint gen/let as core/with-open or something#2020-05-2915:47borkdudeissue welcome#2020-05-2917:59wilkerlucio@borkdude sure, you think this is more a bug or feature request? I'm not sure#2020-05-2918:00borkdudeI think for the redundant let check we should only look at clojure.core/let only, so I would say it's a bug in that linter#2020-05-2918:04wilkerluciocool, another details that I got now: - clojure.test.check.generators/let is already recognized by kondo (before I said I had configured, but I hadn't) - Trying to make it work as with-open didn't fix got around it#2020-05-2918:08wilkerluciohttps://github.com/borkdude/clj-kondo/issues/901#2020-05-2918:12borkdudethanks#2020-05-2922:39borkdudeI also made a proposal for built-in support for core.match into clj-kondo for Summer of Bugs. https://github.com/borkdude/clj-kondo/issues/496 Please upvote the issue with a thumbs up if you'd like to see support for it.#2020-05-3021:36borkdudeExperimenting with sci inside clj-kondo for macroexpansion...#2020-05-3111:00borkdude@dominicm The above might be a solution for your custom try+ macro. Wanna give it a try?#2020-05-3111:30dominicmInteresting! I'll share this with #meander and see what comes up#2020-05-3111:32dominicm@borkdude is there a solution for when you don't know the type, or calculating the actual code form would be costly? My first thought is just to bind to nil#2020-05-3111:36borkdude@dominicm That might result in unused bindings, etc.#2020-05-3111:37dominicmHmm. I guess that matching does check for the presence of the key as well...#2020-05-3111:38dominicmSo I guess I'd need to implement a subset of meander in sci to get kondo to work with it#2020-05-3111:42borkdudeyes, that's the idea. implement a function which expands into something that clj-kondo understands, which mimics the real macro#2020-05-3115:25borkdude@dominicm I believe I have one for slingshot here:#2020-05-3115:45dominicmI think step 1 is implementing meander. Then try/catch should be easy#2020-05-3115:57borkdudePersonally I think this will be a powerful feature. You can even throw exceptions when validating the macro input.#2020-05-3118:53borkdude@dominicm In case you, or anyone else wants to play with this, here is some info: https://github.com/borkdude/clj-kondo/issues/811#2020-05-3119:13borkdudemaybe @seancorfield would also be interested in this, since you recently wrote custom analyzers for jdbc macros which could now be done in user-space with the above.
#2020-05-3121:27seancorfieldI'll take a look when I'm back at work tomorrow. I haven't been following the discussion today.#2020-05-3121:27borkdudethanks!#2020-05-3122:49didibusWouldn't most macroexpand passed to :macroexpand just be the macro code as is?#2020-06-0107:01borkdude@didibus No, E.g. the weird-macro example is similar to jdbc’s with-connection while the clj-kondo macro just expands into constructs that are known but is much simpler #2020-06-0107:02borkdudeOne other point is that clj-kondo has to deal with partial information. So it doesn’t go looking for namespaces elsewhere and find that macro for you#2020-06-0109:40borkdudehttps://clojureverse.org/t/feedback-wanted-on-new-clj-kondo-macroexpansion-feature/6043#2020-06-0116:48dominicm@borkdude have you tried core.match yet? I think that's the killer example for it.#2020-06-0116:49borkdudeI haven't yet, but that's a good one#2020-06-0116:50dominicm@borkdude is it possible to mark a macro expansion as allowing unused variables? Consider an anaphoric macro like proxy(?) where this is bound, but possibly not used.#2020-06-0116:54borkdude@dominicm Do you ask this in relation to the new macroexpand feature or in general?#2020-06-0116:54dominicmThe new macro expansion feature#2020-06-0116:55borkdudeI remember fixing something for proxy-super (https://github.com/borkdude/clj-kondo/commit/0cf0f2933d277c7986620bf31a8caca31c0e68af) But if you're implementing a stand-in macro, then you can just emit this so it will be linted as used.#2020-06-0116:58dominicmHeh, that's true. Hmm. Might be an option then :)#2020-06-0117:06snoe@borkdude that new macroexpansion feature looks great! I left some example macros that I've run across that might be useful to evaluate#2020-06-0117:10seancorfieldCatching up on this thread from yesterday/earlier... So the idea is that you provide, essentially, a dumbed-down version of arbitrary macros in the config so that clj-kondo is better able to parse code and issue correct warnings?#2020-06-0117:11seancorfieldThe example shows it as text that is passed to SCI to evaluate -- would it be better to provide a (quoted) form instead so that folks writing these things can get code assist/syntax checking on the alternative macro definitions?#2020-06-0117:12seancorfield(but, yeah, looks very interesting -- and certainly SCI has allowed Chlorine to do amazing stuff, in user-land, to extend the functionality so the overall approach is sound)#2020-06-0117:46borkdude@snoe Thanks!#2020-06-0117:47borkdude@seancorfield Yes, you provide dumbed down version to teach clj-kondo about the syntax. The reason the code is not quoted is that this is supposed to be part of your .clj-kondo/config.edn and in EDN you can't use arbitrary code (not even quotes).#2020-06-0117:47borkdudeI'm still thinking about a way to refer to another file in that config.#2020-06-0117:48borkdudeE.g.: https://github.com/borkdude/clj-kondo/blob/baf3ff5077101dec2063fdced7a3ddac5c3c40b6/corpus/macroexpand.clj#L11#2020-06-0117:49borkdude@snoe I've already done one for slingshot try+: https://github.com/borkdude/clj-kondo/blob/baf3ff5077101dec2063fdced7a3ddac5c3c40b6/corpus/macroexpand.clj#L23#2020-06-0117:50borkdudeI've been considering reader tags to refer to other files, but I want something that can work in both .edn files and as metadata. Reader tags can break people's code.#2020-06-0117:50seancorfieldAh, good point about EDN not being code-sufficient. What Chlorine did was to have the config be .cljs and treat the whole file as SCI-consumable.#2020-06-0117:51seancorfield(that's harder for kondo which traffics in (unquoted) symbols tho')#2020-06-0117:52borkdudeThat works, but I want the code for each macro to be readable separately, as to not eval all macro stuff if only some of it is needed for linting e.g. one file#2020-06-0117:54borkduderight now I have this:
{:macroexpand {foo/bar "foo/bar.clj"}}
which looks in .clj-kondo/foo/bar.clj for the macro
#2020-06-0118:37borkdude@snoe Did one more test. better-cond, only tested the :let construction:
(ns foo
  {:clj-kondo/config '{:macroexpand {better.cond/cond
                                     "
(defn process-pairs [pairs]
  (loop [[[lhs rhs :as pair] & pairs] pairs
         new-body ['cond]]
    (if pair
      (cond
        (= 1 (count pair)) (seq (conj new-body lhs))
        (not (keyword? lhs))
        (recur pairs
               (conj new-body lhs rhs))
        (= :let lhs)
        (seq (conj new-body :else (list 'let rhs
                                       (process-pairs pairs)))))
      (seq new-body))))

(def f
  (fn [{:keys [:sexpr]}]
    (let [expr (let [args (rest sexpr)
                     pairs (partition-all 2 args)]
                 (process-pairs pairs))]
      {:sexpr (with-meta expr
                (meta sexpr))})))"}}}
  (:require [better.cond :as b]))

(let [x 10]
  (b/cond
    (= x 1) true
    :let [y (inc x)]      ;; binding is recognized
    (= 11 y) (subs y 0))) ;; yay, type error because y is not a string
#2020-06-0118:38borkdudeI'm pretty sure more sophisticated things can be linted, as long as you're willing to provide the stand-in macro#2020-06-0118:41borkdude#2020-06-0118:43snoethat's awesome stuff - I think my dsl approach worked for "regular" looking macros a bit better than the lint-as but this is clearer and more generally applicable.#2020-06-0118:47borkdudeI'll add this to the unit tests 🙂#2020-06-0214:04borkdude@martinklepsch @robert-stuttaford demo for rum defsc macro solved in user space: https://clojureverse.org/t/feedback-wanted-on-new-clj-kondo-macroexpansion-feature/6043/7#2020-06-0214:13borkdudeI welcome you to try this out on a real codebase#2020-06-0309:04robert-stuttafordsweeet will definitely do so 👏#2020-06-0309:06borkdudestill thinking about an idea how macro writers can expose this kind of config in their libs so it can be detected by clj-kondo using some classpath scanning logic#2020-06-0309:09borkdudemaybe that should be left out of scope for the initial release of this#2020-06-0309:12robert-stuttafordhow do i install the version of clj-kondo that has this capability, @borkdude?#2020-06-0309:13borkdude@robert-stuttaford I can provide you a link to a binary or you can check out the source + branch and run it with clojure -A:clj-kondo --lint ...#2020-06-0309:14robert-stuttafordok great i'll try the source thing first#2020-06-0309:14robert-stuttafordshot!#2020-06-0309:14borkdude@robert-stuttaford The branch is macros-sci#2020-06-0309:14robert-stuttafordwhich branch is it 😄#2020-06-0309:14robert-stuttafordzing!#2020-06-0309:17robert-stuttafordhmm i think i may need to try the binary, @borkdude#2020-06-0309:17borkdudewhy's that?#2020-06-0309:18robert-stuttafordso that i can test it the way i use it, in emacs, for the whole project, to eliminate unrelated issues due to testing it this way#2020-06-0309:18robert-stuttafordis that straightforward to do?#2020-06-0309:19robert-stuttafordi should be able to put that config into .clj-kondo/config.edn right?#2020-06-0309:19borkdudemakes sense. you can also try to build it. it's relatively straightforward if you download GraalVM, but I can also save you the trouble by providing new links every time you want to try new commits#2020-06-0309:20robert-stuttafordif there's a how-to i can follow, i'm happy to try do that myself 🙂#2020-06-0309:20borkdudeyes. the code goes to :macroexpand {macrons/macroname "(fn ....)" but the string can also contain the path of a file that's in the .clj-kondo dir.#2020-06-0309:21borkdude@robert-stuttaford https://github.com/borkdude/clj-kondo/blob/master/doc/build.md#2020-06-0309:21borkdudeLet me update it with the latest used GraalVM version. It should be java8-19.3.1#2020-06-0309:22robert-stuttafordgreat thanks - i'll probably only get to this over the weekend!#2020-06-0309:23borkdudeupdated#2020-06-0309:23robert-stuttafordthank you 🙂#2020-06-0309:46Marc O'MorainWe have a namespace with two vars like this:
(defn- identity->Identity
...
(defn- Identity->identity
This causes problems with AOT and calling compile as far as I can tell, since the class files generated have the same names. This might be a nice lint warning for Kondo.
#2020-06-0309:47borkdudeok, issue welcome#2020-06-0311:32dominicmThat seems like a clojure bug#2020-06-0311:34dominicm@marc-omorain https://cemerick.com/2010/08/19/case-insensitive-filesystems-vs-aot-compiled-clojure/ looks like you need to have a case sensitive filesystem. This won't affect a lot of people.#2020-06-0311:34dominicmIt's an operating system issue somewhat.#2020-06-0311:37Marc O'MorainDon’t macOS and Windows have case-insensitive filesystems by default? My mac certainly does.
$ touch foo; touch Foo; ls | grep -i foo
foo
#2020-06-0311:52Janne SauvalaMy work macos has APFS (Encrypted), even tho there should be an option for APFS (Case-sensitive, Encrypted). So looks like they are by default case-insensitive https://support.apple.com/en-gb/guide/disk-utility/dsku19ed921c/mac#2020-06-0312:45borkdudeAny users that experienced a problem in VScode / Calva + clj-kondo's config when opening files from other projects external to the main project directory, this should now be resolved in extension version 2020.5.90.#2020-06-0315:04Ho0manHi everyone, I'm trying to integrate clj-kondo into Spacemacs, In the docs there are two sets of instructions for develop and master branch (but there is no such branch anymore). Which is the default way now to integrate it into spacemacs ?#2020-06-0315:06borkdudeprobably asking in the #spacemacs channel is the best, since there's the most people using it#2020-06-0315:07Ho0manThanks#2020-06-0315:10Ho0manhmm ... do you mean that by branch in that section of docs they mean spacemac's clojure layer's branch not clj-kondo's?#2020-06-0315:11borkdudespacemacs runs clj-kondo as a binary, so there is not a branch of clj-kondo that's applicable to that config#2020-06-0315:12borkdudeI don't remember the docs, I didn't write those#2020-06-0315:12borkdude@U05254DQM?#2020-06-0315:18Ho0manThanks @borkdude#2020-06-0315:06borkdudealthough there might also be some of them here#2020-06-0315:15practicalli-john@ho0man I strongly recommend using Spacemacs develop branch, it has all the fixes and enhancements over the last couple of years. If you look at the Spacemacs home buffer, SPC b h it will show you which Spacemacs version you are on. If you are on 0.200, its master and 0.300 it is develop. If you want to switch over to develop, here are my recommended steps https://practicalli.github.io/spacemacs/install-spacemacs/switch-to-develop.html#2020-06-0315:17Ho0manThanks a lot @U05254DQM#2020-06-0320:32snoe@borkdude in macros-sci does the analyzer get insight into the macro forms? i.e would it be able to determine the position of the declaration of x is? (mydef x 1) x => {:col 8} ?#2020-06-0320:33borkdude@snoe yes, it's metadata on the symbol#2020-06-0320:37borkdude@snoe how it works: the rewrite-clj nodes are converted into sexprs, location metadata gets stored onto the sexprs. so for lists, symbols, that works. for numbers, it doesn't.#2020-06-0320:38borkdudeand then you generate a new sexpr and fix the metadata accordingly. e.g. when you return a new list, you use with-meta to put the original location on that#2020-06-0421:45Adrian Smithhey how does the missing map keys feature work in clj-kondo? What's an example that would make clj-kondo flag this?#2020-06-0421:46borkdude@sfyire do you mean this?
$ clj-kondo --lint - <<< '{:a}'
<stdin>:1:2: error: missing value for key :a
#2020-06-0421:46Adrian Smithah I see, I misunderstood yeah I think so#2020-06-0421:48borkdude@sfyire How did you understand it initially?#2020-06-0421:51Adrian SmithI thought it was some kind of key checking, not sure how that would have worked#2020-06-0421:53borkdude@sfyire clj-kondo also has something like that, although you should configure it yourself:
{:op :keys, :req {:a :string} :opt {:b :int}}
https://github.com/borkdude/clj-kondo/blob/master/doc/types.md
#2020-06-0421:56borkdudeI use it in one place in clj-kondo where I must make a map with 5 keys, of which I always forget at least one. clj-kondo reminds me what additional keys I should provide#2020-06-0421:56Adrian Smiththat's quite cool I didn't realise that was possible#2020-06-0421:58borkdudehttps://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/findings.types.edn#2020-06-0422:00Adrian SmithI'm going to try and see if I can get that working on an example function#2020-06-0422:12Adrian SmithWhat have I done wrong here?#2020-06-0422:12Adrian SmithMy test code looks like this:#2020-06-0422:16borkdude:args should be a vector#2020-06-0422:18Adrian Smithyeah I've put that back in, was just reading some more docs but no dice so far#2020-06-0422:21Adrian Smithah what I should try is updating in case my version is old#2020-06-0422:21borkdudealways a good plan#2020-06-0422:21Adrian Smithjust moved from 2020.01.13 -> 2020.05.09#2020-06-0422:22borkdudeThe type stuff is already from Autumn 2019#2020-06-0422:22borkdude
$ clj-kondo --lint /tmp/foo.clj --config '{:linters
                       {:type-mismatch
                        {:level :warning
                         :namespaces
                         {foo
                          {full-name {:arities {1 {:args [{:op :keys
                                                           :req {:first-name :string
                                                                 :last-name :string}}]}}}}}}}}'
/tmp/foo.clj:5:12: warning: Missing required key: :first-name
/tmp/foo.clj:5:12: warning: Missing required key: :last-name
linting took 43ms, errors: 0, warnings: 2
#2020-06-0422:22borkdude
(ns foo)

(defn full-name [_])

(full-name {})
#2020-06-0422:23borkdudeworks here#2020-06-0422:23borkdudeI'm afk now#2020-06-0422:23Adrian Smithah cool I'll try that out locally thank you for your help#2020-06-0422:40Adrian Smithah it helps if I update the jar file the lsp plugin in cursive is pointed to#2020-06-0514:51serioga@borkdude looks like :unused-import {:level :off} does not work in ns meta...#2020-06-0514:54borkdudeissue welcome#2020-06-0520:36borkdudefixed on master#2020-06-0607:14martinklepschI’m having some config to ignore an unresolved symbol in one particular namespace. My editor integration picks it up correctly but when ran with --config on the CLI it seems the namespace specific configuration is ignored. Is this intentional?#2020-06-0607:15martinklepsch
{:clj-kondo/config {:linters
                      {:unresolved-symbol
                       {:exclude [sentry]}}}}
This is the piece of config. Interestingly my editor integration does NOT pick this up correctly with quotes. ie. '[sentry]
#2020-06-0607:35borkdudeTry quoting the entire config: '{:linters ...}#2020-06-0607:44borkdudeThe config should never contain inner quotes.#2020-06-0609:02borkdude@U050TNB9F So this works:
(ns foo
  {:clj-kondo/config '{:linters
                       {:unresolved-symbol
                        {:exclude [sentry]}}}})

(map sentry [1 2 3])
#2020-06-0719:30martinklepschThat did the trick. Seems a little surprising to me though? Why does the quoting only work in this one place?#2020-06-0719:55borkdude@U050TNB9F Because clj-kondo doesn't evaluate code#2020-06-0719:55borkdudethe quotes are just there to please the clojure who is running the code#2020-06-0719:56borkdudeclj-kondo just reads it as a plain EDN sexprs#2020-06-0719:56borkdudebut for compatibility it supports the outer quote#2020-06-0621:49Adrian SmithPlaying around with the type stuff foo2 gives a warning, foo1 does not, does this warrant an issue?#2020-06-0621:53borkdude@sfyire This does work: (defn foo1 [^long s]) (foo1 "get"). But adding Integer to map to :int would be good I think#2020-06-0621:53borkdudeSo issue welcome#2020-06-0622:07Adrian Smithcool placed it here: https://github.com/borkdude/clj-kondo/issues/910#2020-06-0622:09borkdudethanks#2020-06-0816:26seriogaHello @borkdude Is it realistic to wish that clj-kondo checks function arities using :arglists meta, like here:
(def ^{:arglists '([x])} my-function (comp :b :a))
(my-function) ; <- warning is wanted here
(my-function {:a {:b 1}})
#2020-06-0816:27borkdudeissue is welcome. currently clj-kondo doesn't look at arglists#2020-06-0816:29seriogawhere does it take arity info? parses defn itself?#2020-06-0816:30borkdudeyes#2020-06-0816:32borkdudebut it's probably better to give priority to arglists#2020-06-0816:32borkdudealthough I'm not entirely sure#2020-06-0816:38serioga> although I'm not entirely sure the questionable case I see like
(defn my-function
  {:arglists '([{:keys [a b c]}])}
  [data])
#2020-06-0817:43borkdude@serioga arglists often have informal regex syntax like foo* to indicate multiple foos. that might not make it great for inferencing arity information from it. https://github.com/clojure/clojure/blob/30a36cbe0ef936e57ddba238b7fa6d58ee1cbdce/src/clj/clojure/core.clj#L5787#2020-06-0817:44serioga¯\(ツ)/¯#2020-06-0817:46borkdudealternatively we could deduce that comp always returns an arity-1 function#2020-06-0817:53seriogawell, it you can analyze if def is a anonymous function and use its arity — it also would be cool#2020-06-0817:58seriogano, we cannot
((comp identity +) 1 2)
=> 3
#2020-06-0817:59seriogaso comp produce function with same arity as a rightmost one#2020-06-0818:01borkdudeah right.#2020-06-0909:40eskosI was reading this https://clojuredocs.org/clojure.core/keyword#example-542692d3c026201cdc326fde and had a thought to test this out, and seems clj-kondo doesn’t warn about these non-conformant keywords. Should it/could it?#2020-06-0909:42borkdude@suomi.esko can you give a concrete example that doesn't require me to read this entire page?#2020-06-0910:12eskosHmm, the anchor link doesn’t work for you? There’s a list of non-conformant keywords, eg. (keyword "abc def") (keyword "") (keyword "...") and one I’ve actually seen in production, (keyword ":a")#2020-06-0910:14borkdudethe link works, but I don't have time to read all this, so if you can condense your question that would be helpful. clj-kondo can check those kinds of things, but in general the argument to keyword are runtime values, not literal strings - this is something which clj-kondo cannot check#2020-06-0910:27eskosThat’s the could/should part. I’m not really sure why Clojure hasn’t natively spec’d that part, since it’s quite easy to make all kinds of mangled garble with the keyword function.#2020-06-0910:29borkdudethis topic has come up often in the #clojure channel. I think one of the problems with narrowing down the possible keys is that it would break existing code which clojure will never do#2020-06-0910:30borkdudeyou can always write your own my-keyword function that checks things. one other reason is performance. creating keywords should be very fast in clojure. additional checks will mean a performance penalty#2020-06-0910:48dominicmIn the future these things will maybe be made valid too#2020-06-0910:49borkdude@U09LZR36F in which context do you mean valid? is anything invalid right now?#2020-06-0910:50dominicmWell, :1 isn't valid right now, but it works in some places#2020-06-0910:51dominicmI guess what I really mean is that Alex has hinted that (keyword "foo bar") will eventually print in such a way that it can be (read-string)#2020-06-0910:52borkdudeinteresting, I wonder how they're going to do that#2020-06-0910:52dominicmIt was hinted that the syntax would be something like :|foo bar|#2020-06-0910:53dominicmand | would ergo be the only restricted character.#2020-06-0910:54borkdude:"foo" could also work#2020-06-0910:54dominicmYeah, I recall the pipe character being mentioned explicitly#2020-06-0910:55borkdudeso tl;dr: clj-kondo isn't going to do anything about this 🙂#2020-06-0910:56dominicmhttps://clojurians.zulipchat.com/#narrow/stream/180378-slack-archive/topic/clojure-dev/near/167574595#2020-06-0910:57dominicmI think this was the conversation#2020-06-0911:01dominicmNope, a separate one 😁#2020-06-0911:04dominicmhttps://clojurians.zulipchat.com/#narrow/stream/180378-slack-archive/topic/clojure-dev/near/182433674 this was a good conversation#2020-06-0911:05dominicmhttps://clojurians.zulipchat.com/#narrow/stream/180378-slack-archive/topic/clojure-dev/near/182434173 I guess this one is your tease#2020-06-0911:06dominicmI'm bored of searching now, I swear there was a | syntax though#2020-06-0911:06dominicmmaybe specifically for symbols? Dunno#2020-06-0911:07dominicmhttps://clojurians.zulipchat.com/#narrow/stream/180378-slack-archive/topic/clojure/near/177714921AHA! I was right#2020-06-0911:08dominicmsymbols was the key term#2020-06-0911:13dominicm@U04V15CAJ fwiw, I think the specific typo of (keyword ":ANYTHING") might be worth catching#2020-06-0911:14dominicm(having reflected on it for all of 30s)#2020-06-0911:14dominicmNothing broad, just catching the silly mistake of putting : when using the function#2020-06-0911:14borkdudewouldn't that also be valid in the future with :|:foo|?#2020-06-0913:36dominicmYeah, I suppose it would :)#2020-06-0914:07eskosI’m willing to bet that pipe surrounded form will break backwards compatibility even worse though… 🙂#2020-06-0914:08dominicmI doubt it. Besides, anyone relying on that is relying on something that was never promised.#2020-06-0914:09borkdudeI think the Clojure on DotNet has special syntax which uses this. It will break them#2020-06-1001:02fabraoHello all, how to deal with this ?
(ns app.core
  (:require
   ["react-dom" :as rdom]
   [helix.dom :as d]
   [helix.core :as hx :refer [$]]
   ["antd/es/button" :default Button]
   [emotion.core :refer [defstyled]]
   [app.lib :refer [defnc]]))

(defstyled Div "div"
           {:color :red})
defstyled erro -> Invalid function body
#2020-06-1001:04fabraoSorry, I solved myself -> {:lint-as {emotion.core/defstyled clojure.core/def}}#2020-06-1208:21Kari MarttilaI think I have configured clj-kondo with LSP in IDEA as instructed in https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md ... but I get this error every time I start IDEA:
LanguageServer for definition
 rawCommand : java -jar /mnt/ssd2/local/bin/clj-kondo-2020.05.09-standalone.jar
not initialized after 10s
Check settings
... later on IDEA / clj-kondo shows the linting errors in IDEA editor, though... Just a minor nuisance. Clj-kondo is a great tool!
#2020-06-1208:32borkdude@kari.marttila well, maybe set the timeout for startup greater than 10 seconds then. don't know 🙂#2020-06-1208:52Kari MarttilaOk. Thanks! As I said, just a minor issue. Clj-kondo is a great tool! 🙂#2020-06-1209:03borkdudeclj-kondo v2020.06.12 maintenance release with several fixes and enhancements https://github.com/borkdude/clj-kondo/releases/tag/v2020.06.12#2020-06-1209:12borkdude@kari.marttila you can upgrade to the new version now you're at it anyway 🙂#2020-06-1212:29Kari MarttilaOk. Thanks!#2020-06-1212:30Kari MarttilaI added the timeout from 10s to 20s - haven't seen the error now... 🙂#2020-06-1212:34Kari MarttilaUpdated. Clj-kondo, go strong! 🙂#2020-06-1222:54dominicmhttps://www.commitstrip.com/en/2020/06/11/im-watching-you/#2020-06-1719:27borkdudeI'm soon resuming work on the macroexpand feature and would still very much like feedback on this. https://clojureverse.org/t/feedback-wanted-on-new-clj-kondo-macroexpansion-feature/6043#2020-06-1720:12borkdudeIn a different issue someone suggested it would be useful to have a hook in the function call so you can lint arguments to some function yourself. This would be a generalization of the macroexpand feature as it is proposed now. E.g. with re-frame, a dispatch function should get a qualified keyword. This is something people can't do with the analysis output today (although that could also be extended with the sexpr).#2020-06-1721:44borkdudeso like this:#2020-06-1721:48dominicm@borkdude it would be nice to attach location info somehow#2020-06-1721:48borkdudeone of the problems in the above example is that keywords and numbers don't carry metadata#2020-06-1721:49borkdudealso I think rather than throwing people can return :findings with :level, :row, :col etc.#2020-06-1721:50borkdudeThe row and col come from the metadata of the sexpr elements, but in case of numbers of keywords these aren't present#2020-06-1721:51borkdudeOf course the function could get an additional :node thing which is the raw rewrite-clj node#2020-06-1721:51borkdudeand then you can lookup the metadata yourself#2020-06-1721:52borkdudeusing (-> node :children second meta) for example#2020-06-1721:56dominicmA basic thing to do is point at the argument#2020-06-1721:56dominicmThe rewrite node is most powerful#2020-06-1721:57borkdude> A basic thing to do is point at the argument what do you mean?#2020-06-1721:58dominicmA common use case that it would be nice to make easy.#2020-06-1721:59borkduderight, or a path into the sexpr, like [1 0]#2020-06-1722:00borkdudewhich would mean the second child node and then the first child node of that#2020-06-1722:00borkdudeand then clj-kondo can figure it out#2020-06-1722:05borkdudethis is probably already a power-feature, so the raw rewrite-clj node is probably good to start with#2020-06-1722:07dominicmYeah I think you're right#2020-06-1722:11dominicmI'm not sure you can close 468 from this, as custom linters might be broader, like less than 10 functions per namespace.#2020-06-1722:14borkdudeI followed you until like less than 10 functions per namespace.#2020-06-1722:18borkdudeI mean, then I became confused about what you are trying to say#2020-06-1722:32borkdudewith fixed location:#2020-06-1722:41borkdudeunless people give me more concrete use cases, I don't know what to make of 468 really#2020-06-1722:41borkdudebut I think the macroexpansion -> hooks generalization is a good one#2020-06-1804:01wilkerluciohello, one curiosity, when you have many projects and would like to keep the lint configuration consistent between then, is there a nice way to keep a single file serving many projects?#2020-06-1806:53borkdude@wilkerlucio I recommend writing a babashka script to generate/update your project configs. Clj-kondo has an API function called merge-configs which can also be used for this and can be invoked as a pod function #2020-06-1807:28dominicm@borkdude with 468, it's about linting a single function, it's about linting the whole file. Eg implementing my own version of unused refers, or something like that. Generating an arbitrary message for anywhere in the file.#2020-06-1809:41borkdudeI'm considering switching entirely to rewrite-clj node based transformations instead of converting them to sexprs and parse the transformed sexpr as rewrite-clj nodes again as it's quite difficult to preserve location metadata, for the "macroexpand" feature#2020-06-1809:43borkdudeStill, the sexpr can be used for some validations, when people don't "macroexpand"#2020-06-1810:41borkdudeit's a bit unfortunate since working with sexprs is more ergonomic than rewrite-clj nodes... but preserving location information is really important for clj-kondo#2020-06-1811:07borkdudeColin Fleming posted a response: https://clojureverse.org/t/feedback-wanted-on-new-clj-kondo-macroexpansion-feature/6043/10?u=borkdude#2020-06-1811:11borkdudeI think he just affirmed my belief that it's good to not use sexprs but work directly with the source nodes in that response#2020-06-1819:00Sean PoulterHey folks. Can I bounce a wild idea off someone? I’ve come over JavaScript in the last year and trying to find the Clojure-ish way to walk the AST to find where some of my function calls use third-party libraries. I heard about the analysis output from clj-kondo on Jacek Schae’s podcast, but it seem to have a way to connect the variable usage (call site) to the function that calls it. Does that sound right? I probably need to find something to work with the AST, eh?#2020-06-1819:01Sean PoulterThanks in advance for thinking about it, and a huge thanks to Michiel for sharing all your tools. ❤️#2020-06-1819:02borkdude@sean.poulter Using the analysis output you can see where a third party library is called: https://github.com/borkdude/clj-kondo/tree/master/analysis#2020-06-1819:03borkdudesee :var-usages#2020-06-1819:03Sean PoulterYea, I’ve found the call sites that way which is awesome.#2020-06-1819:03Sean PoulterI don’t think we can find the enclosing function though. I’ve got to walk the call stack to figure out where that third-party code is called from our public APIs.#2020-06-1819:04borkdudeyou want to know the enclosing defining function? you can do that I think#2020-06-1819:05borkdudethere are at least a few tools making visual representations of this using the analysis data, so it should be possible#2020-06-1819:05borkdudelet me have a look#2020-06-1819:06Sean PoulterHere’s an entry from the var-usages:
{ filename: 'src/my/components/widgets/list/views.cljs', 
  row: 14, 
  col: 6, 
  from: 'my.components.widgets.list.views', 
  to: 'other.components', 
  name: 'Flow', 
  'from-var': 'widget' } 
#2020-06-1819:07Sean PoulterOh…. oh. 😐#2020-06-1819:07borkdudefrom-var#2020-06-1819:07Sean PoulterYea… macros!#2020-06-1819:07Sean PoulterThe macros have me all confused. Thanks!#2020-06-1819:08borkdudeso with from-var + from (the ns) you know in which defn this happens#2020-06-1819:08borkdudeI do notice that this isn't in the documentation#2020-06-1819:08borkdudeso sorry for the confusion#2020-06-1819:08Sean PoulterCan I add from-var to https://github.com/borkdude/clj-kondo/tree/master/analysis for you?#2020-06-1819:08Sean PoulterAll good.#2020-06-1819:08borkdudeyes please#2020-06-1819:09Sean PoulterCool. I’ll put something up in the next day or two after work. 🤓#2020-06-1819:09borkdudethanks a lot. there are a few cool tools built on top of this: https://github.com/borkdude/clj-kondo/issues/836#2020-06-1819:10borkdudethese two: https://github.com/SevereOverfl0w/vizns https://github.com/benedekfazekas/morpheus visualize the analysis output in interesting ways#2020-06-1819:11borkdude@sean.poulter I'm also building something like this: https://twitter.com/borkdude/status/1273384546269040646/photo/1 so you can write a hook and make a custom linter once clj-kondo analyses the usage of a function. but it won't be released soon probably#2020-06-1819:11Sean PoulterNeat.#2020-06-1819:12Sean PoulterWow, thanks. I can use Morpheus to solve my “where is this stuff used?” question too! 👏#2020-06-1819:12borkdudeAlso carve is interesting to cut out unused stuff#2020-06-1819:15Sean PoulterWow. That’s neat too! Thanks! 😀#2020-06-1819:16Sean PoulterThis is one of those “I wish I could hang out and watch how (person) works” moments. That’s some really neat tooling we weren’t aware of.#2020-06-1821:46borkdudeanyone want to add clj-kondo to this? https://github.com/github/super-linter https://github.com/github/super-linter/issues/111#2020-06-1908:40borkdudemaybe @delaguardo ^?#2020-06-1908:42delaguardoI already reserve few hours this weekend for that)#2020-06-1908:42borkdude😄 ❤️#2020-06-1910:05borkdudeThis is an example of rewriting a slingshot/try+ call to something clj-kondo understands using the new "hooks" functionality: https://github.com/borkdude/clj-kondo/blob/macros-sci/corpus/.clj-kondo/macroexpand/try_plus.clj#2020-06-1910:05borkdude(cc @martinklepsch)#2020-06-1910:08borkdudeit's not the easiest macro example, but it shows that it's possible to do it. this is an easier one which is syntactically isomorphic to the jdbc with-transaction macro: https://github.com/borkdude/clj-kondo/blob/macros-sci/corpus/.clj-kondo/macroexpand/weird_macro.clj#2020-06-1914:38borkdude@martinklepsch so this is a newer version of a hook that can teach clj-kondo about rum defc: https://github.com/borkdude/clj-kondo/blob/81e3e8a66beaf07c011546ff89b7d7358cd00644/corpus/macroexpand.clj#L74-L111#2020-06-1915:05martinklepschdownloaded this binary and added the config to the ns form of a file but it seems to behave as before#2020-06-1915:05martinklepschI’m pretty sure the right clj-kondo binary is used#2020-06-1915:06martinklepschclj-kondo v2020.06.13-SNAPSHOT#2020-06-1915:10borkdudecan you give me that same file?#2020-06-1915:12borkdude#2020-06-1915:12borkdudeworks for me#2020-06-1915:13borkdudecan you try running clj-kondo --lint rum.clj?#2020-06-1915:13borkdudeit should output:
$ clj-kondo --lint /tmp/rum.clj
/tmp/rum.clj:35:1: error: quux/with-mixin is called with 4 args but expects 1
/tmp/rum.clj:35:13: error: unresolved symbol a
/tmp/rum.clj:37:1: warning: redefined var #'quux/with-mixin
#2020-06-1915:28martinklepschfigured it out by trying to trim down my file#2020-06-1915:28martinklepschthe :hooks key should use the fully qualified macro name
{:clj-kondo/config '{:hooks {rum.core/defc "
#2020-06-1915:29martinklepschbefore the key was just rum/defc#2020-06-1915:29martinklepschbut these macros live in rum.core#2020-06-1915:30borkdudeyeah sorry, that was just for my own tests 🙂 I actually don't use rum so I didn't bother to look what the real ns name was 🙂#2020-06-1915:31martinklepschvery very cool though, seems to work great!#2020-06-1915:40borkdudethanks for testing#2020-06-1915:40martinklepschmy pleasure, very excited to get this into our CI 🙂#2020-06-1915:43borkdudeso how many variations of this defc macro are there, only one?#2020-06-1915:44borkduderum/defcs I see, is that syntactically the same as defc?#2020-06-1915:47borkdudeif so, then adding a lint-as rule for this should work (it doesn't right now, but it can be made so)#2020-06-1916:08borkdudedone: https://github.com/borkdude/clj-kondo/blob/macros-sci/corpus/macroexpand.clj#L74-L120 should now work with this binary: https://9930-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2020.06.13-SNAPSHOT-macos-amd64.zip (cc @U0509NKGK)#2020-06-1917:33martinklepschthere’s also defcc but I think it’s also the same#2020-06-1917:33martinklepschthey basically add extra arguments to the function#2020-06-1917:34martinklepschso as long as the argvec is parsed correctly this should be fine#2020-06-1917:50borkdudeok then lint-as can also be used for that one, nice#2020-06-2320:55robert-stuttafordYAAAAAAAAAAAAY -dance-#2020-06-1914:38borkdudeNote, the string in the config is only for demo, it may also be a filepath relative to the .clj-kondo directory#2020-06-1914:43borkdudeHere's a mac binary: https://9926-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2020.06.13-SNAPSHOT-macos-amd64.zip#2020-06-1914:50borkdudeI might still rename the naming of {:hooks {rum/defc ...}} since this gets invoked during analysis of a call only. so maybe {:hooks {:analyze-call {rum/defc ...}}} might be better for future extension#2020-06-1914:51borkdudeand then we could potentially add more and more hooks#2020-06-1914:53borkdudebut that's a minor detail.#2020-06-1920:09borkdude@delaguardo Seems someone worked on including clj-kondo into super-linter: https://github.com/github/super-linter/pull/197#2020-06-1920:27delaguardoThat's even better) now I have free two hours on weekend)#2020-06-1920:27delaguardo:hugging_face:#2020-06-2320:55robert-stuttafordYAAAAAAAAAAAAY -dance-#2020-06-2011:05borkdudeI think I'm close to a release now#2020-06-2011:06borkdudeLatest example for re-frame/dispatch hook:#2020-06-2011:09borkdudeNow write some docs#2020-06-2012:31wilkerlucio@borkdude nice, this :clj-kondo/config will also support regular clj-kondo config? I wonder if as a library author I can already say things like "this custom macro is just like defn", will that be possible using this ns config?#2020-06-2013:19borkdude@wilkerlucio I consider that a different feature: https://github.com/borkdude/clj-kondo/issues/559#2020-06-2013:19borkdude:clj-kondo/config is just ordinary clj-kondo config#2020-06-2013:28dominicm@borkdude does your example assume literals? Could it be updated to cancel early or use type inference when it isn't a literal? I think it's critical that the examples are comprehensive.#2020-06-2013:31borkdude@dominicm yes, you get the source node as the user writes it. arguments don't get evaluated before you see the source node, that's not how static analysis works#2020-06-2013:31dominicm@borkdude I figured as much.#2020-06-2013:32borkdudetype inference: could be possible, but then I'd need to pass more into the hook function, something like :bindings where a binding can have a tag#2020-06-2013:32borkdudeI consider that something for later#2020-06-2013:32dominicmEither way, the example should cope with vars.#2020-06-2013:33dominicmHow does apply play with hooks?#2020-06-2013:33borkdudeThe :analyze-call hook only gets called when the function is in function position, not as an argument to apply#2020-06-2013:34borkdudeNote that this is mostly for expanding unrecognized macros
#2020-06-2013:34borkdudeThe rest is more or less a bonus#2020-06-2013:56borkdudeHere are some docs: https://github.com/borkdude/clj-kondo/blob/macros-sci/doc/config.md#hooks#2020-06-2014:07borkdudeI want to add more examples of other libraries. In fact I want to make documentation sections for library-specific configs. But this should explain how it works.#2020-06-2016:12borkdude@dominicm you're right, the example fails with (dispatch x ...) or (dispatch (some-fn-producing-a-vector)), so I'll probably just remove it#2020-06-2016:14borkdudewell, the example is still useful when: 1) the users passes a vector with a keyword, but the keyword is unqualified#2020-06-2016:15borkdudealthough you get limited feedback, still useful, like with many other cases where static analysis can only get you so far#2020-06-2016:21dominicm@borkdude Yeah. You just need to be careful about what you lint, I think carefully applied power matters here.#2020-06-2016:24borkdudeUpdated: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#custom-lint-warnings#2020-06-2016:26borkdudeSo this is merged to master now#2020-06-2016:31borkdudeBtw you can also specify the types for dispatch as :vector but that doesn't say anything about the contents of the vector#2020-06-2016:33borkdudeBtw, anyone's open source project is using clj-kondo and you want to share the config, do it here: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#example-configurations#2020-06-2110:13borkdudeExample config for the Rum library: https://github.com/borkdude/clj-kondo/tree/master/libraries/rum cc @martinklepsch @robert-stuttaford#2020-06-2112:03borkdudeclj-kondo v2020.06.21 introduces a new hooks API which allows writing code to support custom macros https://github.com/borkdude/clj-kondo/releases/tag/v2020.06.21 This work was sponsored by Clojurists Together as part of their Summer of Bugs program. Thanks!#2020-06-2114:21dominicmGonna give this a spin, today#2020-06-2116:21dominicmHow do I debug a hook? Like, check the output?#2020-06-2116:25borkdude@dominicm Try (prn (api/sexpr node))#2020-06-2116:25borkdudeBlogged about the new feature here: https://blog.michielborkent.nl/2020/06/21/clj-kondo-hooks/#2020-06-2118:37borkdude@dominicm https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#tips-and-tricks#2020-06-2119:27yuhanThe new hooks API looks interesting! One thing that wasn't clear to me from reading the documentation was whether clj-kondo treats the auxillary files in .clj-kondo as regular namespaces? Eg. If I write my library and put its macroexpand definitons in .clj-kondo/foo.clj, does that conflict with another library's definitions in the same foo ns? Wondering why this isn't namespaced the conventional way with the library name: https://github.com/borkdude/clj-kondo/blob/master/.clj-kondo/macroexpand/one_of.clj#2020-06-2119:46borkdude@qythium clj-kondo doesn't execute any other files than those in .clj-kondo and since there can only be one .clj-kondo/foo.clj file at the same time, there isn't any conflict#2020-06-2123:32yuhanIs this true even when different libraries both have their own .clj-kondo subdirectories?#2020-06-2123:38yuhanSorry, maybe I'm misunderstanding the mechanism for 3rd-party libraries to provide hooks - do they all have to be added via PR to the clj-kondo repo? And curated such that libraries/***/.clj-kondo/hooks/common-name.clj does not conflict#2020-06-2206:58borkdudeAt this time libraries don’t export config. Users have to add it manually #2020-06-2119:47borkdudeand you can load that file using (require 'foo) or refer to it from the config as foo/foo (assuming it has a function foo). having said that, it's a good habit to use at least two segments in a namespace#2020-06-2123:09lreadThanks for the new linting power @borkdude! I’ll see if I can get it working on rewrite-cljc’s internal import-vars-with-mods macro!#2020-06-2123:42yuhanAlso, where does one find the actual API for clj-kondo.hooks-api ? I couldn't find such a namespace defined in the clj-kondo repo, only usages of it.#2020-06-2200:22adamCan clj-kondo reorder my imports alphabetically?#2020-06-2200:29seancorfield@somedude314 A linter isn't a rewriter. I think there are some existing tools out there that will do certain types of rewriting.#2020-06-2200:29seancorfield(but I don't like tools touching my code -- I just want them to tell me what needs fixing)#2020-06-2200:34adamI am so used to gofmt and black, isort & autoflake combo for Python. Wish there was something similar for Clojure. For now I am using cljfmt but it seems to only handle indentation and is too afraid to arrange the code.#2020-06-2200:44lread@qythium, I dug a bit, here’s where the clj-kondo.hooks-api is exposed https://github.com/borkdude/clj-kondo/blob/3531b80a3473177e0b5941c443f921d57f70f0c8/src/clj_kondo/impl/hooks.clj#L64#2020-06-2201:08seancorfield@somedude314 There was a Leiningen plugin that used to reorder ns clauses. I don't remember the name of it, sorry.#2020-06-2201:09seancorfieldI get the impression most Clojurians prefer their tools to be kept simple and to avoid things that rewrite code in any substantial way...#2020-06-2201:11seancorfieldhttps://github.com/technomancy/slamhound -- that's what I was thinking of @somedude314#2020-06-2201:12seancorfield(last updated nearly four years ago)#2020-06-2201:13adamThis looks interesting - https://github.com/immoh/lein-nsorg. I will give them a try soon and report back. Thanks for the pointers.#2020-06-2206:57borkdude@somedude314 I have an example of re-ordering imports using a babashka script using the parcera pod: https://github.com/babashka/pod-babashka-parcera#sort-requires#2020-06-2209:39borkdudeIn emacs I use clojure-sort-ns for this#2020-06-2213:38adamThanks will look into those#2020-06-2209:35borkdude@qythium I added some documentation for the API here now: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#api#2020-06-2219:03lreadOk, cool! I wrote my first clj-kondo hook! I went a bit heavy on the comments on the hook, thinking they might be helpful to others as this is a new feature. https://github.com/lread/rewrite-cljc-playground/commit/09882e1244a8c12879ef8c1e6872724748e7914b#2020-06-2219:13lreadI’m sure @borkdude will let me know if some changes might make sense simple_smile#2020-06-2219:14borkdudeI'm getting an error about Github's IP... 😕#2020-06-2219:14borkdudeMaybe someone can give me the IP of Github?#2020-06-2219:16lreadMaybe you need to reboot computer/router/modem?#2020-06-2219:16lread
ping -c 2 
PING  (140.82.112.3): 56 data bytes
64 bytes from 140.82.112.3: icmp_seq=0 ttl=50 time=49.478 ms
64 bytes from 140.82.112.3: icmp_seq=1 ttl=50 time=40.860 ms
#2020-06-2219:18borkdudedoesn't work for me, it will redirect the browser to https://github.com. I've never had this before#2020-06-2219:19lreadI have, a reboot of my modem and router (and maybe computer?) fixed it for me.#2020-06-2219:23borkdudeswitching to 1.1.1.1 as dns server worked#2020-06-2219:27borkdude@lee Cool! So if I understand correctly, you're generating a series of (def foo fully-qualified.bar)s in a do right?#2020-06-2219:28lreadyes, that’s right#2020-06-2219:29lreadI guess I could have looked at what you coded up to support potemkin import-vars… but did not think of it.#2020-06-2219:30borkdudeThat's fine 🙂 One thing that might be of interest: have you measure performance by linting the calls to your modified import-vars? E.g. by pasting 10000 of them in a file#2020-06-2219:30borkdudeor 1000, I don't know#2020-06-2219:31borkdudeI think using (cons 'do (map ....)) is more performant than (conj (for ...) 'do) , but there's only one way to find out#2020-06-2219:32borkdudethe reason is that for generates a bunch of extra stuff, maybe it doesn't matter#2020-06-2219:33borkdudeI'm happy you figured it out!#2020-06-2219:33lreadfor my little purposes it seems to run just speedily! but am happy to do perf tests if it would be useful to clj-kondo.#2020-06-2219:34borkdudewell, you are the one that's going to use the hook, so if you are satisfied, it's fine. 🙂#2020-06-2219:36lreadYa, I’m good for now with performance. Thanks for yet another linting power! It did not take me terribly long to figure out. Some familiarity with rewrite-clj and a good amount print debugging helped!#2020-06-2219:36borkdude😄#2020-06-2219:37borkdudeOnce this library is published, you can post your config to https://github.com/borkdude/clj-kondo/tree/master/libraries#2020-06-2219:38borkdudeor isn't this thing a public API?#2020-06-2219:38lreadIt is an internal macro that exposes a public API.#2020-06-2219:39lreadSoo… how does that fit in? simple_smile#2020-06-2219:40lreadSo folks won’t be using the internal macro but will be using the public API it exposes.#2020-06-2219:40borkdudewell, that's not something that's going to affect linting of end user programs then#2020-06-2219:41lreadYeah, makes sense.#2020-06-2219:47lreadI’m a big foggy and rusty though… will clj-kondo be able to warn on incorrect calls to rewrite-cljc’s public API if rewrite-cljc exposes that API through internal import-vars trickery?#2020-06-2219:49borkdudeAdded your example here for now: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#examples#2020-06-2219:50borkdude@lee Not right now, I think. Let me try.#2020-06-2219:50lreadGood idea, hope it helps others.#2020-06-2219:50borkdudeSo no:
(defn foo [x])

(def f foo)

(f 1 2 )
#2020-06-2219:51borkdudebut that could be fixed. If you expand to potemkin's macro, it does work#2020-06-2219:51borkdudeI'd rather fix it in clj-kondo though, much nicer#2020-06-2219:52borkdudeit's this issue: https://github.com/borkdude/clj-kondo/issues/412#2020-06-2219:52borkdudeI'll bump it.#2020-06-2219:52lreadcool!#2020-06-2220:00borkdudeI remember that we discussed this macro roughly a year ago, I was in Leuven at Heart of Clojure then 🙂#2020-06-2220:00lreadah… sweet memories!#2020-06-2220:02lreadclj-kondo was just a wee baby back then!#2020-06-2307:04epquestion about future approaches to macros. does the addition of hooks mean that the https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#unrecognized-macros documented here: Clj-kondo only expands a selected set of macros from clojure.core and some popular community libraries will not be supported anymore in favor of us developing our own hooks? my question is if i want to contribute by updating or adding new built-in support for a macro, should i be exclusively developing hooks or will built-in support for libraries like compojure continue to be maintained?#2020-06-2307:34borkdude@epransky Macros that are already supported will remain supported. Macros that are very common can eventually move from hooks to built-in supported.#2020-06-2307:35epthanks 🙂#2020-06-2307:36borkdudeE.g. if someone figures out a hook for core.match, it can be moved inside clj-kondo#2020-06-2307:49yuhanIs there a limitation to why we can't write nodes as plain expressions instead of using the api syntax?#2020-06-2307:51yuhanlike an inverse of the sexpr function#2020-06-2307:52borkdude@qythium Yes. I've explained it here: https://blog.michielborkent.nl/2020/06/21/clj-kondo-hooks/#2020-06-2307:55yuhanah, I didn't understand that point the first time round. Thanks!#2020-06-2307:57borkdudeAlso this is more performant. Going from rewrite-clj -> sexpr -> hook -> sexpr -> rewrite-clj takes more operations than rewrite-clj -> hook -> rewrite-clj#2020-06-2307:58borkdudeBut loss of information is the main reason I abandoned the idea#2020-06-2312:08lreadI wonder if hooks docs should link to your blog, it is very helpful. Either that or extracting a few key phrases from the blog to the hooks docs.#2020-06-2312:27borkdudePR welcome!#2020-06-2312:28lreadWill do!#2020-06-2318:45rschmuklerHey! Does the new hooks API allow for allowing for different linting based off of clojure and clojurescript mode? I have a cljc macro for RPC that boils away the body on the cljs side (and instead does an RPC call) and behaves like a defn on the clj side. Since I'm conditionally requiring the clj libraries, lint-as clojure.core/defn doesn't work for me.#2020-06-2320:02borkdude@rschmukler Currently there is nothing to go by in the hook, but I could add a :lang key that will contain either :clj or :cljs if that's helpful#2020-06-2321:08rschmukler@borkdude that'd be wonderful! It might also be worth including a :lang-via which could indicate that the file is cljc. I'm not immediately sure that this is useful at all, so feel free to consider it and ignore it if you can't think of a use case!#2020-06-2321:09borkdude@rschmukler In clj-kondo itself I use a ctx map which has :base-lang :cljc and :lang :cljs for example#2020-06-2321:10rschmuklerThat's perfect#2020-06-2321:12rschmuklerAlso, have you considered somehow allowing libraries to communicate with the hooks library directly? It'd be cool if downloading a library via clojars automatically gave me linting, similar to how typescript allows types to be packaged up in NPM modules.... ie. Could library authors somehow get you clj-kondo hooks for free without requiring you modify the config...#2020-06-2321:12rschmuklerNot sure if it's a road you want to go down, but maybe worth thinking about#2020-06-2321:13borkdudeI have thought about that: https://github.com/borkdude/clj-kondo/issues/559 For now I suggest library authors to post their configs here: https://github.com/borkdude/clj-kondo/tree/master/libraries Maybe eventually we can have some tool which can inspect the classpath and harvest these configs for you#2020-06-2406:57ep@borkdude currently this is just a reference right? kondo doesn't merge these configs right?#2020-06-2406:59borkdudeCorrect #2020-06-2321:13rschmuklerHmmmmm and now that I'm thinking about it - giving hooks access to the config could be useful then#2020-06-2321:14rschmuklerie. imagine if a library auto packages itself with hooks, maybe it has its own clj-kondo settings#2020-06-2321:14rschmuklerI'll check out the issues, thanks for the replies! Super excited for the hooks API, I think it could really be something special if the community widely adopts it#2020-06-2321:15borkdudeThank you#2020-06-2321:52borkdude@rschmukler Could you maybe add an issue about those extra keys, in case I forget#2020-06-2322:06rschmuklerWill do!#2020-06-2413:37borkdude@rschmukler added the keys on master. feel free to experiment with them#2020-06-2414:51rschmukler@borkdude awesome, thanks so much!#2020-06-2505:30vermahello everyone, I am trying to lint a defrecord but it seems like I am not getting unresolved vars reported, I am trying this snippet in the lint playground:
(+ a b)

(defrecord wow [a b]
  (some [_]
        (+ a b whatisthis)))
#2020-06-2505:31vermaI can get a and b to report correctly in my first statement, but whatisthis is not being reported as unrecognized/unresolved#2020-06-2505:37vermaoof#2020-06-2505:37vermaI think there is some syntax problem, I cannot declare that function some without an interface/symbol of somekind#2020-06-2505:38vermaTrying with this now:
(+ a b)


(defprotocol IAbc
  (doit [_]))

(defrecord abc [a b]
  IAbc
  (doit [_]
    (+ a b whatisthis)))
#2020-06-2505:41vermastill doesn't seem like its being reported, am I missing something?#2020-06-2505:57borkdude@verma clj-kondo might not have good analysis yet for the protocols part of defrecord, I’ll take a look when I’m at a keyboard #2020-06-2505:58vermathanks @borkdude :thumbsup:#2020-06-2506:01vermaI am trying to write an analyzer for defcomponentk from https://github.com/plumatic/om-tools/blob/master/src/om_tools/core.cljc#L257 using the new :hooks stuff in clj-kondo#2020-06-2508:01borkdude@verma awesome! I checked and clj-kondo has pretty crude analyzing for defrecord's protocol parts at the moment. it basically lints it, with some things turned off. https://github.com/borkdude/clj-kondo/blob/466930149b0c8c3b50fab0df5c6d2fb482a03cb8/src/clj_kondo/impl/analyzer.clj#L926 There is room for improvement there, but now you know why it is like it is.#2020-06-2508:03borkdudeThere is an old issue for it: https://github.com/borkdude/clj-kondo/issues/140 But I never got to it yet.#2020-06-2508:04borkdudeMeanwhile I did implement protocols in babashka/sci, so at least I have more understanding of it now 😉#2020-06-2508:05borkdudeBumped it a little bit in the "medium priority" column: https://github.com/borkdude/clj-kondo/projects/1#2020-06-2517:36vermathanks so much!#2020-06-2600:38rschmuklerHey @borkdude - just played with the new hooks API you pushed and confirmed that it handles my use case perfectly! Thanks!#2020-06-2600:43rschmuklerPs. your documentation on graal, etc was fantastic. As an aside, when trying to build with JVM 11 based graal I ran into the same issue that I presume lead you to write https://github.com/borkdude/clj-reflector-graal-java11-fix - worth noting that adding that as a dep to clj-kondo's :clojure-1.10.2-alpha1 profile didn't seem to fix it for me. Ultimately I just used a java 8 based graal - happy to submit a PR to the clj-kondo compile docs clarifying that you need a JDK 8 based build if you think that bug is expected. Sorry I didn't have time to dig further.#2020-06-2606:08dominicmForgot to mention, I also have this working :)#2020-06-2606:37borkdudeA doc PR and issue to upgrade to 11 are both welcome #2020-06-2612:41borkdudeclj-kondo is now part of github/super-linter! https://github.com/github/super-linter#2020-06-2814:23souenzzoHello I'm developing a inspector/plugin tool Does kondo has a function like this:
(kondo/resolve {:sym 'clojure.core/+ 
                :classpath "...."})
=> [{:file "clojure/core.clj"
     :line 123
     :jar "org/clojure/clojure.jar"
     ....}]
#2020-06-2815:02borkdude@souenzzo You could maybe utilize the analysis output for this:
clj-kondo --lint - --config '{:output {:analysis true :format :edn}}' <<< '(defn foo []) (foo)'
{:analysis {:var-definitions [{:filename "<stdin>", :row 1, :col 1, :ns user, :name foo, :fixed-arities #{0}}], :var-usages [{:name defn, :filename "<stdin>", :from user, :macro true, :col 2, :arity 2, :varargs-min-arity 2, :row 1, :to clojure.core} {:filename "<stdin>", :row 1, :col 16, :from user, :to user, :name foo, :fixed-arities #{0}, :arity 0}]}}
#2020-06-2817:35souenzzoMost of kondo output is just about current project. I need also info about dependencies#2020-06-2819:02borkdudeThen you'll need to lint also the dependencies#2020-06-2820:56souenzzoWow I can
(kondo/run!
  {:lint (string/split "....my giant classpath...."
                       #":")})
Nice. Thanks
#2020-06-2820:58borkdudeYou don't have to split the classpath, clj-kondo understands classpaths#2020-06-2820:59borkdudeso just {:lint [the-classpath]}#2020-06-2821:00borkdudeif you use this option: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#output-canonical-file-paths clj-kondo will also output the .jar file under :filename#2020-06-2815:03borkdudeIn the above example it outputs the definition of user/foo in the file <stdin> and the usage of user/foo also in the file <stdin>#2020-06-2815:03borkdudeOther work in this area is https://github.com/didibus/anakondo#2020-06-2906:25reefersleepHello @borkdude 🙂 I am trying out super-linter with
VALIDATE_ALL_CODEBASE: false
          VALIDATE_CLOJURE: true
, and, curiously, it seems to pick up and validate e.g. YAML and JSON files are validated. That’s one issue; I thought that, according to the super-linter docs, once you turn on a specific validator, you turn off the rest. It’s not my real issue, though. My real problem is the following:
File:[project/src/my_ns.clj]
  - WARN! Failed to get filetype for:[project/src/my_ns.clj]!
#2020-06-2906:26reefersleepHave you seen anything like that before?#2020-06-2906:27reefersleepI wanted to ask at the #super-linter channel on whatever medium, but there is none linked at the super-linter github repo.#2020-06-2906:28reefersleepSo, sorry to bother you about what I guess is essentially not a problem with clj-kondo 😅 Just thought you might have some input regardless.#2020-06-2906:53eskossuper-linter is GitHub’s native tool (the repo is owned by GitHub itself, in case you missed that) so you probably should ask through the repo’s Issues about that one.#2020-06-2908:02reefersleepThanks @suomi.esko. I thought it’d be a bit much to ask via something like Issues when I had no clue whether there was an error in the code or an error in my thinking. Maybe this is customary, though? I tend to ask more informally first, like in Slack 🙂#2020-06-2908:03borkdudeThat's fine#2020-06-2908:03reefersleepWhich one? Asking in Issues when I don’t know if the Issue is actually with the code? 🙂#2020-06-2908:04borkdudeAsking everywhere is fine with me. But super-linter is so new that you probably have the most luck at the repo itself#2020-06-2907:58borkdude@reefersleep Yes, like @suomi.esko, it's probably best if you post an issue there. Do you know which version you are running? The version with clj-kondo in it might not be published yet, it came after 2.2.0#2020-06-2908:00reefersleep@borkdude I don’t understand that; the version I tried was 2.2.0, the documentation mentioned Clojure at that point. In any case, I bumped it to 2.2.2, and that didn’t work either. A colleague of mine pointed out the error in the lib/linter.sh script, and I opened up a PR which hopefully fixes the problem: https://github.com/github/super-linter/pull/300/files#2020-06-2908:01borkdude2.2.2 was a typo, I meant 2.2.0, I don't think there is a newer published version yet#2020-06-2908:01borkdudecool!#2020-06-2915:02slimslenderslacks@reefersleep speaking of super-linter, the company I'm at is also going to provide similar support for running clj-kondo. If you're interested in trying it, it's available at https://go.atomist.com/catalog/skills/atomist/clj-kondo-skill (also requires that you install a GitHub app). We're focusing on enabling tools to run on events, and then push data back to be evaluated by other functions. Ultimately, we're working towards being able to say things like "IF clj-kondo had no violations, AND the security check passed, AND the unit tests succeeded, THEN ...). IFTTT for delivery so to speak#2020-06-2915:05borkdudeLooks interesting#2020-06-2915:06slimslenderslacks@borkdude one of the things I've been excited about is the possibility of potentially sharing configurations across Repos.#2020-06-2915:06borkdudeFeel free to submit to the docs once you're ready. Maybe https://github.com/borkdude/clj-kondo/blob/master/doc/ci-integration.md is a good place for it#2020-06-2915:07borkdude@slimslenderslacks That's cool. Can you also share code files that are necessary for hooks (which is a new feature)?#2020-06-2915:09slimslenderslacksWill do, thanks! The code that we run is here: https://github.com/atomist-skills/clj-kondo-skill/blob/master/src/atomist/main.cljs. I actually had not thought about hooks but these things have parameters (https://github.com/atomist-skills/clj-kondo-skill/blob/master/skill.edn#L28) so probably could look at ways to share hooks too. That's really interesting.#2020-06-2915:10slimslenderslacksThe first thing that interested me was using public urls (e.g gist urls) to share configurations between teams. Among our own clojure repos, that certainly helps us.#2020-06-2915:13slimslenderslacksAnd that kind of sharing was easy to add. It seems to me like there could be value in sharing libraries of linter rules anyway. I'll take a look at hooks as well.#2020-06-2915:14borkdudeThese are some examples: https://github.com/borkdude/clj-kondo/tree/master/libraries#2020-06-2915:29slimslenderslacksRight! So one of the things we've added is the ability to reference a config by url. So, for slingshot, we could pull in for all projects that have slingshot in the CP.#2020-06-2915:31slimslenderslacksI don't have an instinct for how practical this is.#2020-06-2915:32borkdudeThat could work, but what about the code in the slingshot dir?#2020-06-2915:32borkdudeSo, this: https://github.com/borkdude/clj-kondo/blob/master/libraries/slingshot/.clj-kondo/hooks/slingshot/try_plus.clj#2020-06-2916:44slimslenderslacksI see ... if the config has hooks, you really would have to be able to pull down the hook code too. So if I was a library owner, I could ship a config.edn, AND hook code to users of my library.#2020-06-2916:45borkdudeyes#2020-06-2916:45borkdudeclj-kondo doesn't automatically import that (right now) so you have to copy that code yourself to your own .clj-kondo#2020-06-2916:48slimslenderslacksI'll see if I can get this to work on the serverless runner. So far, it seems like it should be possible to merge several libraries by referencing their github coords.#2020-06-2916:49borkdudeclj-kondo has a merge-configs API function to merge configs btw#2020-06-2916:31borkdudeclj-kondo now has docs for coc.neovim: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#cocnvim Thanks https://github.com/sittim#2020-06-3018:48slimslenderslacksIs it true that you can add metadata to an ns definition:
(ns x.y
  {:clj-kondo/config {:linters {:unused-binding {:level :off}}}})
#2020-06-3019:21borkdude@slimslenderslacks Yes, but it might not be supported by all linters yet. If it doesn't, please post an issue and it will get fixed.#2020-07-0100:39slimslenderslacks@borkdude I'm trying to deploy a new version of the clj-kondo skill with support for running hooks. But I think that borkdude/clj-kondo:latest has version clj-kondo v2020.06.12 and that does not have support for hooks yet, right?#2020-07-0101:15slimslenderslacksAlso, I think this is a quick question. My current understanding of hooks is that the config.edn {:hooks {:analyze-call {macro-symbol hook-symbol}}} could be merged from anywhere so as long as I can get that data into command line --config it should be available to clj-kondo. However, the code for the hook itself has to be in the :cfg-dir so that it can be required. Looking at the code, maybe it could also be slurped if we were to use a form like {:hooks {:analyze-call {macro-symbol "my/hook.clj"}}}``. I've only been trying to do this with symbols so far but I want to confirm my understanding that the :cfg-dir plays a crucial role here. I guess that's .clj-kondo by default.#2020-07-0107:23borkdude@slimslenderslacks 2020.06.21 is the latest version, includes hooks#2020-07-0107:23borkdudesee https://clojars.org/clj-kondo#2020-07-0114:43slimslenderslacksSorry, what I really had meant to ask was about the docker image currently tagged latest But looking closer, it seems like that's on 2020.06.21 as well. So that should have hooks support.#2020-07-0114:44borkdudeit should yes#2020-07-0416:05futurileI'm trying to use clj-kondo with the docker file. I can't seem to get it to use the cache directory. I'm running this command:
sudo docker run -v $PWD/src:/src -v $HOME/.m2:$HOME/.m2 -v $HOME/.clj-kondo:$PWD/.clj-kondo borkdude/clj-kondo clj-kondo --cache-dir=$HOME/.clj-kondo --lint "$(lein classpath)" 
The way I'm reading the project setup section, I'm expecting to see it generate files in the project's .clj-kondo directory but it's not creating anything in there. Am I running the command incorrectly or have I misunderstood?
#2020-07-0416:13borkdudeThe way you mount files into the docker container looks a bit inconsistent maybe#2020-07-0416:13borkdude
-v $HOME/.clj-kondo:$PWD/.clj-kondo
#2020-07-0416:14borkdudethat doesn't look right#2020-07-0416:14borkdudeshould probably be -v $PWD/.clj-kondo:/.clj-kondo or something?#2020-07-0416:15borkdudesince you also mount: -v $PWD/src:/src#2020-07-0416:15borkdudealso the cache-dir looks weird.#2020-07-0416:16borkdudeNote that $HOME gets expanded in your shell before it goes into docker, at least I think so#2020-07-0416:17borkdudeMight be best to just bash into the container and look around#2020-07-0416:19futurilemakes sense - I'll try and attach to the container and poke around#2020-07-0419:16slimslenderslacksI would think something like
docker run -v $HOME:$HOME borkdude/clj-kondo clj-kondo --cache-dir=$PWD/.clj-kondo --lint "$(lein classpath)"
should work as long as PWD is somewhere in HOME. Since lein classpath evaluates outside of docker, that classpath string has to end up making sense to clj-kondo running inside docker. I think you might be able to add -w $PWD to set the working dir, and then not have to set --cache-dir since .clj-kondo is the default. So
docker run -v $HOME:$HOME -w $PWD borkdude/clj-kondo clj-kondo --lint "$(lein classpath)"
When I ran this on my project, I found that it gave me the same results as if I ran without docker (including running the hooks in my local .clj-kondo)
#2020-07-0516:04futurile@U0143KP47M4 thank-you! that worked, wrote to my cache dir. It makes sense, I've got it checking my source properly now I believe.#2020-07-0813:52dominicmRandom thought (rooted in how many of these I have due to react) that I wanted to get some basic feedback on before opening an issue: linting unused arguments when calling a function which destructures in it's arglist.#2020-07-0813:53dominicm
(defn foo [{:keys [a b]}])

...

(foo {:c 10})
For react, this is a lot of code because of props.
#2020-07-0813:53dominicmObviously it only works for literal maps, but I still think it's pretty useful for that?#2020-07-0814:03borkdudeWhat do you mean with unused arguments?#2020-07-0814:03borkdudeSomething else than clj-kondo already does apparently?#2020-07-0814:10dominicm*unused parameters that should be#2020-07-0814:11dominicmSo in the above example you'd lint :c is not a used key#2020-07-0814:16borkdudeI don't think Clojure works that way in most cases: data is passing through all the time which is not used in one place but maybe down the line#2020-07-0814:21dominicmIt would be specifically for arglists destructuring where :as is not used.#2020-07-0814:36borkdudeI think in most cases Clojure doesn't care about extra keys, except maybe in edges of systems#2020-07-0814:37dominicmWouldn't be an error, for sure. It's for when something is removed from use I guess.#2020-07-0814:38dominicmHmm, which would be a breaking change I guess. Only in internal use is it not. So perhaps not a good choice. But then again, arglists are warned about.#2020-07-0814:38dominicmThe change that got me here was removing a keyword arg from a component, and then replacing uses of that arg with a different one.#2020-07-0815:22borkdudeclj-kondo does have an option to check for required keys#2020-07-0816:45dominicmI don't see that in the list of optional linters, could you point me the right way?#2020-07-0818:40borkdude@dominicm it's part of the type stuff: https://github.com/borkdude/clj-kondo/blob/master/doc/types.md so you explicitly have to state the required and optional keys for a function's argument#2020-07-0818:40borkdudeI use it in one place in clj-kondo where I need to construct a map with 5 keys of which I always forget one#2020-07-0918:36slimslenderslacks@borkdude I made some changes to https://go.atomist.com/catalog/skills/atomist/clj-kondo-skill around referencing config urls and hooks. The goal of this was to make it possible to reference urls like in the configuration, and then have this library's config.edn, along with it's hooks, merged into clj-kondo's config. For me, it was an experiment to see if I could use this to develop some hooks that can be shared across all of our Clojure Repos.#2020-07-0918:39slimslenderslacksAdding linting checks to a lot of existing projects has the challenge of not overwhelming people with data they might not understand. So being able to kind of tune it before making the Check visible seems really interesting to me.#2020-07-0919:56borkdudeThanks for the update!#2020-07-1110:00epi've got a question about the new hooks API. i'm trying to write a hook for defstate macro from https://github.com/tolitius/mount lib. this macro supports adding certain https://github.com/tolitius/mount#on-reload. i would like to lint this metadata node as well, but i cant figure out how to access it through the hooks API. it seems not be parsed into rewrite-clj node. example:
(ns example
  (:require [mount.core :as mount]))

(mount/defstate
  foo
  ^{:on-reload :noop}
  :start (do (prn "start") {:bar "buzz"}))
and in hooks ns:
(ns hooks.defstate
  (:require [clj-kondo.hooks-api :as api]))

(defn defstate [arg]
  (prn arg))
clj-kondo lint produces: {:node <list: (mount/defstatefoo:start(do(prn"start"){:bar"buzz"}))>} is this intended behavior? is it possible to access {:on-reload :noop} map?
#2020-07-1111:24borkdude@epransky The metadata node is accessible by fetching :meta on the node#2020-07-1111:27borkdudeI've deviated from vanilla rewrite-clj here to make parsing easier and not check for metadata node everywhere#2020-07-1111:28epthanks. if i understand correctly i should expect (:meta (:node arg)) to return {:on-reload :noop} ?#2020-07-1111:31borkdude@epransky In the form (defn ^{:cool true} foo []) the metadata node for {:cool true} is part of the node for the symbol foo#2020-07-1111:31borkdudejust like in normal clojure where you expect the metadata to be attached#2020-07-1111:32borkdudehowever, your defstate example looks a bit weird, keywords can't have metadata in Clojure#2020-07-1111:35borkdudeBut maybe that's what you are trying to lint. The metadata should probably go onto the symbol#2020-07-1111:36epyes you are right. mistake by me. double-checking#2020-07-1111:38borkdudeTry: (doseq [c (:children (:node arg))] (prn c '-> (:meta c))) or something similar#2020-07-1111:39epah, found it. after fixing the mistake to:
(mount/defstate
^{:on-reload :noop}
  foo
  :start (do (prn "start") {:bar "buzz"}))
(:meta (second (:children node)))
thank you!
#2020-07-1119:57seriogaYou can put meta after foo but without ^#2020-07-1111:53borkdude@epransky Added some docs for it here now: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#clojure-code-as-rewrite-clj-nodes (cc @lee)#2020-07-1111:55epthanks. appreciate the help#2020-07-1112:07lreadNice!#2020-07-1117:00ep@U04V15CAJ just to follow up on this, i thought about it and IMO we should be able to lint the metadata forms. like what if im trying to warn a user that the metadata declaration is not in the correct position, such as the mistake i initially made? i cant see a way for me to achieve this functionality if i need to rely on correct placement of the form. wdyt?#2020-07-1117:05borkdudewell, you can check for :meta on the symbol node and if it's not there, emit a warning?#2020-07-1117:05epwhat if meta is optional?#2020-07-1117:06borkdudethen lint accordingly?#2020-07-1117:09borkdudeis your question: what logic should I use for my problem, or is it a matter of clj-kondo not enabling you somehow to do it?#2020-07-1117:09epbut the issue is that there is a form being passed which should not be there and the user might think they've configured some metadata when they havent. it seems that this is what linting is for. i actually think my mistake above illustrates perfectly:
(mount/defstate
  foo
  ^{:on-reload :noop}
  :start (do (prn "start") {:bar "buzz"}))
the metadata here is an optional functionality of the defstate API. i accidentally put it after the symbol instead of before. shouldnt linting help me out here to notify me that i cant put metadata on a keyword, as you pointed out?
#2020-07-1117:10borkdudeyeah, so you can check for :meta on the keyword and then emit a warning right?#2020-07-1117:16epyeah. its possible. just seems a bit roundabout instead of just parsing the meta as a node of its own, but i guess its workable#2020-07-1117:17borkdudewhat do you mean with "instead of just parsing the meta as a node of its own"? I'm not sure if I understand#2020-07-1117:23epim not sure what im thinking about is possible or logical, but when i started using the hooks API, i expected to the meta form to be a node in the children list of the macro. instead, what's necessary is to check each child node to see if it has meta and extract it. just seems like a lot of extra work than if the meta was first class in this situation#2020-07-1117:26borkdudeAh that. Well, what rewrite-clj has by default is even more annoying: if you have ^:foo [] then the structure is the metadata node is the parent of the vector node. It's now structured this way because if it wasn't you'd constantly be checking if a node is metadata and if so, go down into the children for the thing you're actually looking for.#2020-07-1117:27borkdudee.g. when clj-kondo analysis (defn foo []) you expect the second thing to be a symbol, but when users write (^:foo defn ^:bar foo []) then clj-kondo can still expect the name of the function to be the second child.#2020-07-1117:29borkdudeSo that's the reason it is like it is now and that's unlikely going to change#2020-07-1117:31epi see. i agree clj-kondo is better. but i guess my issue is just that intuitively i see a certain number of forms in a list and i expect the children of the parent node to have the same number of forms. but i get the thought and as long as its documented i think ppl will learn to work with it#2020-07-1117:31borkdudethe way clj-kondo structures it also matches how it works in clojure itself: the second child is the symbol and if you want metadata from that, you call meta on it#2020-07-1117:37lreadya, I do like clj-kondo’s rewrite-clj metadata node scheme better than rewrite-clj’s.#2020-07-1117:49epyeah i get the thought. thanks for explaining#2020-07-1220:51slimslenderslacks@epransky I've been working on a way to share hooks across projects. Coincidentally, mount comes up a lot (popular library!). If your .clj-kondo directory ends up being public, I'd love to try adding those hooks to other projects.#2020-07-1305:52epsure. here's my WIP: https://gist.github.com/ethpran/e1741a5c408aec831b5e3a7e24f40fea. let me know what you think. im still testing it so it will very probably change#2020-07-1317:10slimslenderslacksGreat, thanks! I'll add this hook to my tests. Appreciate it!#2020-07-1405:34epcan you link me to the project? ill contribute there#2020-07-1520:19slimslenderslackshey @epransky, sorry for taking so long to respond. The project repo is here: https://github.com/atomist-skills/clj-kondo-skill but it probably requires a bit of explanation.#2020-07-1520:23slimslenderslacksThe idea is to allow users to attach clj-kondo to their GitHub pushes. It produces annotated GitHub checks and ideally, makes it easy to share configuration (including hooks) across Clojure projects. On most projects, especially new ones, we want clj-kondo checks to be there by default.#2020-07-1520:26slimslenderslacksHowever, it's actually been quite a challenge to roll this out to existing clojure projects without spending some time doing some analysis of the violations, and preparing teams. One of the big challenges is that you need hooks (like your mount example) to be ready to add to all of the projects that use mount!#2020-07-1520:29slimslenderslacksWe experimented with a few things: • only neutral checks - don't break the build until you've had a chance to work on the violations. However, the number of annotated violations can impact the usability of PRs! • don't publish annotated violations until you've at least cleared the violations in the project once, and then turn them on to help keep them at zero? And the hypotheses is that one thing we can do to be prepared to help people take advantage of this is to be ready with a good starting configuration, including hooks.#2020-07-1520:30slimslenderslacksSo when I configured this across our team's repos, I included a reference to your gist, so that it merged your config and hooks into all of the clj-kondo run across all of our Repos.#2020-07-1520:33slimslenderslacksYou're welcome to use this on your repos if you want to try it out. It requires that you enable our GitHub app, but it's free to use.#2020-07-1605:32epok, ill have a look. thanks for the explanation!#2020-07-1615:03slimslenderslacksCool, and if you want to enable it on a Repo, you'll actually need to do 3 things: • signup with GitHub https://go.atomist.com/user/signup • enable our GitHub app (on at least a few Repos in one of your Orgs) https://go.atomist.com/r/auth/manage/integrations/add/GitHubAppResourceProvider • and then enable this clj-kondo function to run: https://go.atomist.com/catalog/skills/atomist/clj-kondo-skill The config where you can add your gist url is called "Custom configuration URL" (probably not a great name)#2020-07-1222:08ziltiIs there some kind of option for cljc files that it only shows imports as unused if they actually are unused, and not just unused by the clj part?#2020-07-1222:08borkdudeclj-kondo lints a .cljc file twice: once for clj and once for cljs#2020-07-1222:10ziltiHmm so I figure that'd be something for the flycheck plugin to "fix" then? It's just... I really enjoy having clj-kondo, but having your file littered with "unused import" and "unused argument" warnings is a tad annoying. How do people usually deal with that scenario?#2020-07-1222:10borkdudeto answer your question: that option does not exist and the reason for it is the way .cljc files are processed (similar to how they are processed in Clojure itself)#2020-07-1222:10ziltiYea, it makes sense to have it linted twice, once for each "mode"#2020-07-1222:12borkdudeyou can turn off that linter for that namespace locally, using metadata config. it's implemented, but not yet released, see: https://github.com/borkdude/clj-kondo/issues/932#2020-07-1222:13borkdudeI actually like the way clj-kondo handles .cljc and I tend to fix all warnings by marking unused bindings for one branch with _foo and the other one with foo.#2020-07-1222:14ziltiHow do you handle function args when the function body is split? Having #? inside the arg vector seems very messy#2020-07-1222:15borkdudeif you find that too messy, you can duplicate the entire arg vector once for clj and another time for cljs, but I tend to choose the inline version.#2020-07-1222:15borkdudeI'm afk now, sleep#2020-07-1222:16ziltiOkay. Thanks!#2020-07-2011:56reefersleepThis is more a question about opinions on style: clj-kondo warns against unused function parameters. I use Cursive, which already does that. So now, I have both a greyed out symbol (Cursive) as well as a squiggly line underneath the symbol clj-kondo. They really want this to be visible! However, some “functions” are e.g. defmethod s, implementations of a defmulti. Having the names of the parameters repeated in each defmethod makes the code easier to scan as the signature makes those particular defmethod s very visible, and Cursive signals to the person reading the function that parameter x isn’t used anyway, so they can ignore it. Therefore, could it not be argued that changing x to _ detracts from the readability of the code (at least in Cursive)? Similarly, a defmulti may take arguments x and y, but only use x in the default implementation. If x and y are well-named to give some context to the function, don’t we lose something by renaming y to _, like clj-kondo and Cursive wants us to? Implementers of defmethod s for the defmulti will have less context to go on.#2020-07-2011:57reefersleepThis could be argued for any function, really, defmulti and defmethod s just seem particularly vulnerable to loss of context, imo.#2020-07-2012:01borkdude@reefersleep You can still use names like _x and _y though?#2020-07-2012:02reefersleepWell, that solves my problem. Didn’t know about that! Cheers @borkdude!#2020-07-2012:05reefersleepFunny thing, though; doing this means that the symbols are no longer grayed out, which makes it harder to scan for me, initially, at least. (a signature of [_ _] is quick to scan, [_person _vehicle] is less so)#2020-07-2012:07reefersleepAnd while the convention might show that _-prefixed symbols are unused, they could _actually_ be used further down, now that they are shown in the same manner as other symbols (not grayed out). The same goes for _, I guess, but it seems less risky.#2020-07-2012:08reefersleepSo from my perspective, maybe _x should be saved for special cases, and I’ll go with _ for the majority of cases.#2020-07-2012:08borkdudeAs long as you are happy 🙂#2020-07-2012:09reefersleepI’m reasonably happy 😄#2020-07-2310:29martinklepsch@borkdude finally got around to set up the Rum hook but there’s something to still figure out, with defcs and defcc there’s an implicit first argument. Since that is not passed at callsites, clj-kondo will say the function is called with the wrong arity. Would be happy to try to adapt the hook to support that. Do you think that’d require custom hooks or can it be made to work with the same lint-as approach?#2020-07-2310:30borkdude@martinklepsch If the arities are different, then the hooks probably need to be slightly different as well. I wasn't aware of that detail, sorry. I know @robert-stuttaford is also using the hook. Hasn't he ran into this yet? Maybe he doesn't use defcs?#2020-07-2313:06robert-stuttafordyes, we also have this, just haven't gotten round to doing the good opensource citizen thing and writing it up 😞#2020-07-2513:48borkdudeA PR fixing the reference config is welcome from either of you#2020-07-2310:32borkdudePR welcome for the reference config#2020-07-2310:48martinklepsch@borkdude I think I’m close. Ttrying to construct a modified argvec using this (api/vector-node (rest a)) but somehow not quite doing what I expect:
INPUT <vector: [state r]> 

OUTPUT <vector: [[:format-string "[%s]"][:wrap-length 2][:seq-fn #object[clojure.core$vec 0x3ac6c820 "
#2020-07-2310:48martinklepschAlso worth noting, printing the args vector node seems to omit spaces so the <vector: [state r]> above is actually printed as <vector: [stater]>#2020-07-2310:49borkdude@martinklepsch what is a?#2020-07-2310:49martinklepsch<vector: [state r]>#2020-07-2310:50borkdudeyou probably need (rest (:children a))#2020-07-2310:50borkdudeSee the hooks docs, they explain this#2020-07-2310:50borkdudehttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md#hooks#2020-07-2310:51martinklepschI found out about vector-node reading this but don’t know much about rewrite-clj so missed the :children bit#2020-07-2310:51martinklepschanyways, this seems to work#2020-07-2310:51borkdudenp#2020-07-2310:52martinklepschnow the issue however is that the first arg isn’t known inside the function#2020-07-2310:52martinklepsch:thinking_face:#2020-07-2310:52borkdudeyou can fix this by introducing an artificial let binding with that name, bound to e.g. nil#2020-07-2310:52borkdudefor the implicit arg right#2020-07-2310:52borkdude(let [state nil] ... body ...)#2020-07-2310:53borkdudetake a look at the hook for slingshot, it also uses this approach I think#2020-07-2310:54martinklepschcool, will do!#2020-07-2310:54borkdudehttps://github.com/borkdude/clj-kondo/blob/4b42da6fb17764f31a754c4cbe107433255f79d7/libraries/slingshot/.clj-kondo/hooks/slingshot/try_plus.clj#L12
#2020-07-2313:44borkdude@martinklepsch Any luck with that?#2020-07-2313:45martinklepschgot sidetracked by some other stuff after realizing that it’s not just a static token but could also have different names or be a destructuring form#2020-07-2313:52borkdudein that case you should use the first element of the binding vector and then put that in the artificial let binding#2020-07-2313:53borkdude(defn foo [stuff ...] body) => (defn foo [...] (let [stuff nil] body))#2020-07-2405:15JP Silvahi folks, just wanted to check something before submitting a bug. I'm using clj-kondo plugin version v2020.6.21 with visual studio code on MacOS Catalina. Whenever I :require a namespace within my project without providing an alias (`:as`) the first occurrence of a loaded var in the current namespace will result in a "unresolved symbol" error. The subsequent occurrences of the same var won't show the error. Similarly, if the var indeed does not exist, only the first occurrence shows the error and not the subsequent ones. Below is a screenshot of the issue. In this case the some-fn-define-in-bar is defined in the namespace bar.#2020-07-2405:16JP Silvashould I go ahead and submit a bug? Or am I doing something wrong?#2020-07-2405:20seancorfield@jplfdsilva Kondo only reports the first use of an undeclared var. It doesn't "see" any vars when you use :refer :all, I believe. You either need to use an alias or explicitly :refer the vars by name -- using :refer :all is poor practice.#2020-07-2405:20seancorfieldYou'll see there's a warning on :all which will tell you not to do that 🙂#2020-07-2405:20seancorfieldSo, not a bug: expected behavior.#2020-07-2405:42JP Silvagot it! thanks!#2020-07-2405:44seancorfieldIf it's any consolation, we use :refer :all in a lot of our test files and I'm slowly changing that so clj-kondo is happy 🙂#2020-07-2405:45JP Silvamy use case is unit testing where I thought it would make sense to :`refer :all` vars#2020-07-2405:46JP Silvabut if that's how it is, that's ok. thanks for the quick response!#2020-07-2405:46seancorfield(we have 278 occurrences in 266 files -- and only two of those are not test files -- so it'll take us a while to "fix" them all)#2020-07-2405:47seancorfieldI've started doing :as sut for the "system under test" and that's actually quite nice because then I can easily tell what's being tested vs what is just a supporting function: everything being tested is sut/some-function.#2020-07-2405:48seancorfieldFor test files that are short and only refer to a couple of functions from the test namespace, I :refer them by name. And I also :refer by name the vars from clojure.test and expectations.clojure.test.#2020-07-2405:54JP Silvanice! thanks for the tip!#2020-07-2406:23borkdude@jplfdsilva clj-kondo can resolve the :refer :all-ed vars, but then you need to lint that namespace first.#2020-07-2406:23borkdudeElse it has no way of knowing.#2020-07-2406:24borkdudeSee https://github.com/borkdude/clj-kondo#project-setup#2020-07-2406:29JP Silvawill take a look, thanks!#2020-07-2406:31borkdudeBut in general :refer :all isn't recommended. In places where you think it should be used, you can turn the warning off using config.#2020-07-2513:56borkdudePushed support for a new linter around clojure.core/format to master. Thank @mpenet for the idea.#2020-07-2615:14borkdudeNew release: https://github.com/borkdude/clj-kondo/releases/tag/v2020.07.26#2020-07-2617:50ericdalloHey @borkdude, I really like clj-kondo work and I think it's better than clojure-lsp in parse/lint. I thinking if it worth/would be better for clojure-lsp use the option 1 from here: https://github.com/snoe/clojure-lsp/issues/66, I could help @snoe with that#2020-07-2617:52borkdude@ericdallo You mean option 1 from this comment? https://github.com/snoe/clojure-lsp/issues/66#issuecomment-587406393#2020-07-2617:53ericdalloYes! sorry for not clarifying that#2020-07-2617:56borkdudeIt's up to @snoe 🙂#2020-07-2617:57ericdalloYeah, I think clj-kondo has evolved a lot since the creation of this issue, and maybe we can think in some integration where user can opt-in/out from clj-kondo if we want#2020-07-2621:29ericdallo@cnly's branch looks promissing and It seems we almost resolved that issue, I think the issue got lost for some reason, but I asked it again: https://github.com/snoe/clojure-lsp/issues/66#issuecomment-664042668#2020-07-2714:33snoe@ericdallo I replied in the issue#2020-07-2714:36ericdalloThanks! Excited about that 🙂#2020-07-2718:28sparkofreasonHas anybody gotten timeout errors using the linter-kondo package with atom/chlorine? If so, is there a workaround?#2020-07-2718:29sparkofreasonRunning clj-kondo from the command line seems to work fine.#2020-07-2816:50borkdudeIs that the Atom package? Then maybe @seancorfield knows, or @gerred#2020-07-2816:52seancorfield@dave.dixon I've never seen timeout errors with Atom and clj-kondo.#2020-07-2816:52seancorfield(and I use Atom + Chlorine + REBL + linter-kondo all day, every day on a 100k line codebase)#2020-07-2817:10gerredI haven't had time to maintain it as of late with everything going on...if you open an issue and can identify what's going on, I'm happy to make you a maintainer @dave.dixon (or @seancorfield, not that you needm ore to do ;))#2020-07-2817:18seancorfieldIf it breaks and you're no longer around, having maintainer rights would certainly be useful 🙂 Otherwise, I don't think I'd have time to add that to my list of projects.#2020-07-2817:19sparkofreasonI've never seen it before now, new install on Linux. I'll get the exact error from the console.#2020-07-2817:31borkdudemaybe the clj-kondo binary itself is not installed yet or not on the path?#2020-07-2818:44sparkofreasonclj-kondo is on the path. It was working intermittently. I just did a full restart, maybe that will clear it up, haven't seen the timeout so far.#2020-07-2818:48sparkofreasonSpoke too soon. Here's the error from the console:
[Linter] Error running linter-kondo Error: Process execution timed out
    at /home/dave/.atom/packages/linter-kondo/node_modules/sb-exec/lib/index.js:89
(anonymous) @ /home/dave/.atom/packages/linter/lib/linter-registry.js:154
#2020-07-2820:14sparkofreasonI increased the lint-on-change interval in the linter package. I think the default 300ms is probably too low, and that may have been the source of the timeout.#2020-07-2820:26borkdudeHmm, maybe clj-kondo got slower, or your machine got slower? 😉#2020-07-2820:32sparkofreasonDon't know. It's a fresh linux install. Increasing the interval didn't actually solve the problem in the end. I'm having a vague hunch the problem may be something about the generic linter package, rather than specific to clj-kondo.#2020-07-2911:37borkdudeSome users have experienced a few false positive clojure.core/format warnings with the new clj-kondo. I have a fix for this on master. Could anyone who ran into this check if this is fixed with:
$ clojure -Sdeps '{:deps {clj-kondo/clj-kondo {:git/url "" :sha "91b6c55f5290fcfa9032ab221a6fc1b79af18827"}}}' -m clj-kondo.main --lint src test
#2020-07-2917:38borkdudePushed out a new version: https://github.com/borkdude/clj-kondo/releases/tag/v2020.07.29#2020-07-3019:55tanzoniteblack
echo '(require '\''clojure.tools.logging)(clojure.tools.logging/logf "cat" 1)' | clj-kondo --lint -
pretty cool that we now get errors for formatting. How would I go about making clj-kondo recognize the matching functions from timbre ( https://github.com/ptaoussanis/timbre )
echo '(require '\''taoensso.timbre)(taoensso.timbre/logf "cat" 1)' | clj-kondo --lint -                                                                                                                                                                          130 ↵
linting took 6ms, errors: 0, warnings: 0
#2020-07-3019:56borkdude@tanzoniteblack if timbre uses the exact same syntax as clojure.tools.logging or clojure.core/format, you can use :lint-as#2020-07-3021:01tanzoniteblackthanks!#2020-07-3020:26Grant Isom@borkdude Is there a way to use use multiple config files in the vscode extension? My cli command is clj-kondo --lint src --config .clj-kondo/project_config.edn and am trying to add the proj specific linters to what is used in VSCode.#2020-07-3020:39borkdudeCurrently not. Why don't you rename .clj-kondo/project_config.edn to .clj-kondo/config.edn? Then it will work#2020-07-3020:40Grant IsomWe have a global linter file we share between a bunch of projects, then have config files that are merged with specific things per project.#2020-07-3020:42borkdude@grant.isom Right. I think it's best to write a script that uses clj-kondo.core/merge-configs to spit out the merged config in your .clj-kondo/config.edn. You can write this script using clojure but also with babashka (since clj-kondo can be invoked as a babashka pod).#2020-07-3020:42borkdudeSee https://github.com/borkdude/clj-kondo/#babashka-pod for an example.#2020-07-3020:42Grant IsomAwesome, will take a look. Thanks!#2020-07-3119:33Grant Isom@borkdude I opened a PR to clj-kondo.lsp to add the ability in the settings of the extension. Its a small change, but I think it useful.#2020-07-3120:14borkdude@grant.isom Awesome, I'll take a look soon. How do you edit these settings on VSCode? Is there a GUI or something for it?#2020-07-3120:16Grant Isom@borkdude You add some config to the package.json, then you can specify the field types and read from them. I am making a couple quick updates to let it accept anything just like cli would.#2020-07-3120:17borkdudeExcellent. That would be most flexible#2020-07-3120:17Grant IsomI also just kinda guessed on the description text and name, let me know if there is something better suited.#2020-07-3120:18borkdudeI'll let you make the updates and let me know when I should look again#2020-07-3120:19Grant IsomSounds good!#2020-07-3121:34Grant Isom@borkdude Updated#2020-07-3121:36borkdudeok, it's getting late here, so I'll take a look tomorrow#2020-08-0109:11borkdude@grant.isom Left a review as remarks inline in the code.#2020-08-0214:06borkdudeI wonder how useful people would find a linter that warns if you shadow a var with a local name. I fear that people would be interested initially, but after a while, they would turn it off because it's so common to call a local e.g. val or key.#2020-08-0216:15practicalli-johnI would find it useful to have a linter that highlights local names shadowing vars, but then I strive for highly readable code as meaningless names are quite difficult for me to work with.#2020-08-0216:20borkdudeI have trouble parsing the first half of that sentence#2020-08-0216:45practicalli-johnFixed...#2020-08-0216:48borkdude:thumbsup:#2020-08-0221:48seancorfieldI would find it very helpful, as long as I could turn it off for certain symbols on a per-namespace basis.#2020-08-0221:49seancorfieldFor example, I have a couple of namespaces where I want function arguments and let bindings to use name but in general I would want a linter to tell me not to do that.#2020-08-0401:29vemvI find it definitely useful, Eastwood does it (and without issues other than its usual relative slowness) In specific legacy projects it's unfeasible to retrofit things though Also occasionally it's very hard to come up with a good local name that doesn't shadow the defn it comes from#2020-08-0312:49Charlie BriggsHey, is the current intention for users of clj-kondo to copy and paste the hook definitions of libraries into each project using those definitions? E.g copying hooks/slingshot if using Slingshot?#2020-08-0312:53borkdude@charliebriggs Currently, yes#2020-08-0312:54borkdudeIf you found something in the READMEs confusing about this, please let me know and I'll change it#2020-08-0312:55Charlie Briggsgreat, I think it would help if that was more explicit in the Libraries section, i.e. directly calling out the process of adding them for now something like: > Configuration for external libraries can be setup in each clj-kondo project by copying the required library configuration into the .clj-kondo directory. See libraries for a collection of existing configurations#2020-08-0312:58borkdudeI have wondered if using a different name like reference-config or something would be clearer#2020-08-0312:58borkdudePR welcome for the text change btw#2020-08-0312:58Charlie Briggscool, is there any way for libraries to package these configurations currently which can then be picked up by clj-kondo, or is something like that on the roadmap?#2020-08-0313:00borkdude@charliebriggs It is something I've been thinking about and there is an issue for it. https://github.com/borkdude/clj-kondo/issues/559 It's just not that clear cut yet.#2020-08-0313:00Charlie Briggsgreat, thanks for your help!#2020-08-0313:00borkdudeRight now I recommend writing a script that merges and copies all your favorite configs into the right places#2020-08-0313:01borkdudeBabashka can be used for this if you want to do it in Clojure#2020-08-0313:01borkdudeclj-kondo exposes a function called merge-configs to merge clj-kondo configuration#2020-08-0407:29Cnly@borkdude Hi! I’m working on the integration of clj-kondo and clojure-lsp. I know that if I pass a directory to kondo then it’ll be able to see usages, etc. between files. But for LSP’s use case, I actually need kondo to lint the file that the user is currently editing (i.e. not on disk yet) together with those already written to disk. What will be a recommended way of doing that?#2020-08-0407:30borkdude@cnly clj-kondo.core/run! accepts :lint which is a seq of paths#2020-08-0407:30borkdudea path can be a single file or a directory, in which case all files in the directory will be linted (recursively)#2020-08-0407:32CnlyIf I pass e.g. ["src" "-"] to run! where I feed the current file in memory through stdin, kondo will see the on-disk version and the in-memory version of the current file at the same time.#2020-08-0407:32borkdudeTrue. Why do you want to lint them all at once btw?#2020-08-0407:33borkdudeThe way it normally works is that the user edits a file, clj-kondo lints it and saves information to .clj-kondo/cache. Along the way it builds up more and more information about the linted files in the cache.#2020-08-0407:34CnlySo you mean, we only need to lint the whole directory once, and then as the user edits a file, we just feed that single file to kondo, right?#2020-08-0407:35borkdudeyes#2020-08-0407:35CnlyAnd information about references between files will still be remembered and used?#2020-08-0407:35borkdudeyes#2020-08-0407:35CnlyOh, cool. Let me try that. Thanks!#2020-08-0418:07nivekuilhi, not sure if this is in scope as a bug but core.async/go-loop appears to have a false positive; the first arg is for binding but I get an unresolved symbol x e.g.`(go-loop [x 1] x)`#2020-08-0420:01borkdude@kevin842 Full repro please. Here it works fine.#2020-08-0420:06nivekuilyeah, you're right, the false positive is with me :) I had replaced clojure.core.async with just core.async somehow.#2020-08-0420:11borkdudeok, no problem#2020-08-0505:30tjbhey friends! has anyone noticed this error before? i am getting this with a fresh lein luminus template#2020-08-0505:38seancorfield@tjb Presumably because clj-kondo doesn't know what mount/defstate does? (which it won't by default until you tell it that is like a def form)#2020-08-0505:40tjbinteresting! i wonder why luminus does (mount/defstate ...)#2020-08-0507:26borkdudeYou probably need {:lint-as {foo.bar/defstate clojure.core/def}} in your config#2020-08-0613:02CnlyQuick question, does clj-kondo give warnings about unused public functions?#2020-08-0613:03borkdude@cnly No. But there is a tool for this based on clj-kondo: https://github.com/borkdude/carve#2020-08-0613:04Cnly:thumbsup: Thanks!#2020-08-0616:56Karol Wójcik@borkdude Is there a tutorial or docs how to test & write custom hooks? I would love to tweak rum.core/defcs in free time#2020-08-0617:01borkdude@karol.wojcik This is the most recent one: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#hooks#2020-08-0617:27Karol WójcikThank you very much! Why there is :node in keys instead of node?#2020-08-0617:31Karol Wójcik@borkdude Btw I'm trying to find the exact source of clj-kondo.hooks-api. This is what I got so far:
(defn defcs
  [{:keys [node]}]
  (let [args (rest (:children node))
        component-name (first args)
        args (next args)
        body
        (loop [args* args
               mixins []]
          (if (seq args*)
            (let [a (first args*)]
              (if (vector? (api/sexpr a))
                (do
                  (println a)
                  (println (api/vector-node (vec (rest (api/sexpr a)))))
                  (cons (api/vector-node (vec (rest (api/sexpr a)))) (concat mixins (rest args*))))
                (recur (rest args*)
                       (conj mixins a))))
            args))
        new-node (with-meta
                   (api/list-node (list* (api/token-node 'defn) component-name body))
                   (meta node))]
    ;; (println (api/token-node 'defn))
    ;; (println new-node)
    {:node new-node}))
But this throws unsupported binding form input
#2020-08-0618:04borkdude:node or node are both supported, doesn't matter#2020-08-0620:11Karol Wójcik@borkdude I think that I should ignore state somehow, but dunno how to do it. Can you please give me a hint? For instance simply ignoring the first argument results in input not being known.#2020-08-0620:12borkdudeYes. You should probably wrap the body in an artificial let expression that has a binding state, like (let [state nil] ... body ...)#2020-08-0620:13borkdudeTake a look at the hook for slingshot, which also does something similar#2020-08-0620:14borkdude@U050TNB9F @U0509NKGK Any ideas?#2020-08-0707:38Karol WójcikFinally got it working
(defn defcs
  [{:keys [node]}]
  (let [args (rest (:children node))
        component-name (first args)
        args (next args)
        body (loop [args* args
                    mixins []]
               (if (seq args*)
                 (let [a (first args*)]
                   (if (vector? (api/sexpr a))
                     (cons a (concat mixins (rest args*)))
                     (recur (rest args*)
                            (conj mixins a))))
                 args))
        partial-state (api/list-node [(api/token-node 'partial)
                                    (api/list-node (list* (api/token-node 'fn) body))
                                    (api/token-node 'state)])
        new-node (api/list-node
                  [(api/token-node 'let)
                   (api/vector-node
                    [(api/token-node 'state) (api/token-node {})])
                   (with-meta (api/list-node [(api/token-node 'def)
                                              component-name
                                              partial-state])
                     (meta node))])]
    {:node new-node}))
#2020-08-0707:38Karol WójcikThank you for help @borkdude you are golden!#2020-08-0707:41borkdudeCool! What is the partial state for?#2020-08-0707:43Karol WójcikIt's for making sure that state is provided#2020-08-0707:43borkdudeI think this generates something like:
(let [state {}] (def my-component (partial (fn [...] ...) state)))
Why not:
(defn my-component [args] (let [state {}] body)
?
#2020-08-0707:44Karol WójcikIs there a difference?#2020-08-0707:44borkdudeSyntactically yes, clj-kondo can see the argument count this way for example?#2020-08-0707:45Karol WójcikSo in partial it's not seen?#2020-08-0707:45borkdudeYou might want to do:
(defn my-component [args] (let [state {}] state ... body ...)
to make state being used, so it won't be reported.
#2020-08-0707:45borkdudeNo#2020-08-0707:45Karol WójcikHmm....#2020-08-0707:46Karol WójcikFrankly I want the state to be reported#2020-08-0707:47borkdudeah#2020-08-0707:47borkdudethat's ok then, don't use it#2020-08-0707:47Karol WójcikAhh wait.#2020-08-0707:47borkdudeso if you don't use state, then you're going to use def-something-else in rum right?#2020-08-0707:47Karol WójcikSo I can just ignore the first arg?#2020-08-0707:48borkdudewhy would you want to ignore the first arg?#2020-08-0707:49Karol WójcikI think that we are talking past each other 😄#2020-08-0707:49borkdudeI think so too. Maybe it's better to talk in examples. Paste an example of Rum usage and the desired sexpr for clj-kondo#2020-08-0707:57Karol Wójcik@borkdude My goal is to make sure that both not used state is reported and function that takes like 2 (except state) args then when I provide only one argument then I want clj-kondo to report that not all function parameters are passed. Let the demo.cljs be defined like so:
(rum/defcs SomeComponent <
  {:did-mount (fn [state] state)}
  [state input another]
  (let [x "Hello"]
    nil))

(rum/defc SomeComponent1 <
  {:did-mount (fn [state] state)}
  [input]
  input)


(SomeComponent "hello")
After running clj-kondo I got the following things reported:
demo.cljs:9:4: warning: unused binding state
demo.cljs:9:10: warning: unused binding input
demo.cljs:9:16: warning: unused binding another
demo.cljs:10:9: warning: unused binding x
linting took 17ms, errors: 0, warnings: 4
That's perfectly fine. What I need more is just the warning that not all parameters to function has been passed. My question is how I can have that last warning working? What I understand is that I should not use 'partial, but how should I construct sexpr?
#2020-08-0708:33borkdude@karol.wojcik I think more like (defn my-component [args] (let [state {}] body), so more like how it was originally, but with the extra let around the body#2020-08-0710:01borkdude(defsc foo [state x] body1 body2) => (defn foo [x] (let [state {}] body1 body2)#2020-08-0710:02borkdudeSo you call it as (f 1) and clj-kondo will think this is correct, since the generated form only receives one arg (or n-1 args in general) and state is still recognized as a valid binding.#2020-08-0710:03borkdudeand (f 1 2) should trigger an arity warning#2020-08-0710:05Karol WójcikThanks.. Will try to do it in free time#2020-08-0710:06borkdude:thumbsup:#2020-08-0617:03borkdude@karol.wojcik Note: I edited the link, posted an old one earlier#2020-08-0821:36wilkerluciohello, is there a way to make clj-kondo ignore a namespace in the project?#2020-08-0918:16borkdude@martinklepsch @robert-stuttaford fwiw, there is a new commit on clj-kondo master which (hopefully) fixes the hook example for rum/defcs#2020-08-1019:09plinshow can I exclude the symbol thrown+? from being linted globally? its added by slingshot as an extension of a multimethod, so there is no namespace attached to it :unresolved-symbol {:exclude [(thrown?+)]} is not working 😕#2020-08-1019:10dominicmThat's only within clojure.test, it's not global#2020-08-1019:12borkdude@plins The way you're using that config is that it will ignore unresolved symbols inside calls to thrown?+. If you want to ignore the unresolved symbol itself you simply write thrown?+ instead of (thrown?+)#2020-08-1019:12borkdudeFull config: {:linters {:unresolved-symbol {:exclude [thrown?+]}}}#2020-08-1019:13borkdudeYou can also attach this on the test namespace's metadata so it will only exclude it there#2020-08-1019:13plinsit was supposed to be nested inside linters, thank you very much 😄#2020-08-1019:14borkdudemaybe even better:
{:linters {:unresolved-symbol {:exclude [(clojure.test/is [thrown?+])]}}}
#2020-08-1019:14borkdudeso then it will only ignore it within clojure.test/is#2020-08-1019:15borkdude^ @plins#2020-08-1019:16plins#2020-08-1019:16plinsam I missing something?#2020-08-1019:18borkdudecan you show the ns form of your test file?#2020-08-1019:19plins
(ns zendesk-app.unit.domain.user-test
  (:require [clojure.test :as t]
            [integrant.core :as ig]
            slingshot.test
            [zendesk-app.boundaries.frontend.protocol :as fe]
            [zendesk-app.boundaries.oauth.protocol :as oauth]
            zendesk-app.domain.user.impl
            [zendesk-app.domain.user.protocol :as sut]
            [zendesk-app.helper :as h]))
#2020-08-1019:20borkdudeand your usage of the symbol?#2020-08-1019:21plins
(t/is (thrown+? #(= % expected-err)
                      (sut/fetch user-service
                                 (:customer-id expected-user)
                                 (:user-id expected-user)
                                 (:zd-token expected-user))))
#2020-08-1019:23Derekthrown+? vs thrown?+#2020-08-1019:23Derek+? and ?+#2020-08-1019:23borkduderight#2020-08-1019:23plinsoh sorry for that >.<#2020-08-1019:29plinsI know hooks are the way, but Im wondering if there is already some example somewhere on to configure slingshot macros (`try+` and its special catch)#2020-08-1019:31borkdudeAs a matter of fact, there is: https://github.com/borkdude/clj-kondo/tree/master/examples/slingshot#2020-08-1305:14maxpIn that script
#!/usr/bin/env bb
;; (require '[babashka.classpath])
(babashka.classpath/add-classpath ".")
clj-kondo shows deprecation warning for clojure.core/add-classpath is that correct?
#2020-08-1305:17maxpthere is no such warning when I uncomment require line.#2020-08-1305:19borkdudeProbably a bug. Can you make an issue?#2020-08-1308:02maxphmm... or may be it is Calva's mistake#2020-08-1308:02maxphow clj-kondo intended to work with babashka scripts?#2020-08-1308:07maxpYes. that was when I connect to Clojure repl but open babashka script in editor.#2020-08-1308:11maxpThat was a little bit confusing when clj-kond tells about clojure.core/add-classpath underlining babashka.classpath/add-classpath#2020-08-1308:13maxpBut what about ,cljb extensions? 🙂 it is the time to introduce!#2020-08-1308:14dominicmKondo should know those two things aren't the same :) regardless of file extension for bb or not.#2020-08-1308:15dominicmDoes the error happen when running kondo from the cli?#2020-08-1308:26borkdude@maxp I can't reproduce with the above:
$ clj-kondo --lint /tmp/foo.clj
/tmp/foo.clj:4:2: warning: Unresolved namespace babashka.classpath. Are you missing a require?
linting took 10ms, errors: 0, warnings: 1
#2020-08-1308:27borkdudeOf course if you only write add-classpath unqualified, clj-kondo is going to think it's from clojure.core and then it's indeed deprecated#2020-08-1408:57FiVoHey, I am wondering if the unresolved symbol in the destructuring of the following example is intended ?
(defn foo [x {:keys [y] :or {y x}}]
  (list x y))
Is that considered bad style or a bug?
#2020-08-1410:23yuhanIt's undefined behaviour: https://github.com/borkdude/clj-kondo/issues/782#2020-08-1417:30borkdudeThanks for answering this.#2020-08-1417:09seancorfield
(ns foobar
  {:clj-kondo/config {}}
  (:require [ :as io]))
^ Does not flag io as an unused namespace. Remove the :clj-kondo/config metadata and it works:
(ns foobar
  #_{:clj-kondo/config {}}
  (:require [ :as io]))
#2020-08-1417:13seancorfieldI don't see an existing issue for this, shall I go ahead and create one @borkdude?#2020-08-1417:17seancorfieldNever mind. I updated to the most recent clj-kondo version and the problem went away!#2020-08-1417:17seancorfield(FYI, the above bug was in the 2020.04.05 version)#2020-08-1417:28borkdude@seancorfield Could be an issue with parsing the clj-kondo config. Before it expected quotes like
{:clj-kondo/config '{}}
but this has been relaxed to
{:clj-kondo/config {}}
if your config doesn't contain any symbols.
#2020-08-1417:29borkdudeNote that
(ns foobar
  {:clj-kondo/config 1}
  (:require [ :as io]))
won't give you an error about io being unused either, since the parsing of the config fails, so maybe it's similar to what you had
#2020-08-1417:56seancorfield@borkdude I had ' in the real code example. What I posted was just the minimal example of the bug (which has clearly since been fixed).#2020-08-1417:57seancorfieldIt was definitely parsing the config correctly: it contained a :lint-as and without the form, Kondo flagged every use of that macro as an error.#2020-08-1417:58seancorfieldI didn't realize I was on such an old version of Kondo.#2020-08-1417:58borkdudeHope you are enjoying the new one#2020-08-1417:58seancorfield(I'm refactoring old test code right now so Kondo is helping me cleanup ns forms as I swap out uses of an old lib for uses of a new one!)#2020-08-1418:02borkdude@seancorfield I think the most exciting new features since 2020.04.05 are hook support (for handling weird macros that don't work with :lint-as) and linting for clojure.core/format.#2020-08-1418:02borkdudeAnd a whole bunch of tiny fixes.#2020-08-1418:02borkdudeThe thing you did for jdbc can now be done in user-land using hooks. The hooks are evaluated using sci (because a GraalVM binary cannot clojure.core/eval).#2020-08-1418:07seancorfieldYeah, I haven't had time to look at hooks yet, but they look very interesting.#2020-08-1418:07borkdudeAt the moment it's probably mostly used by Rum users#2020-08-1418:08borkdudeHere's some examples: https://github.com/borkdude/clj-kondo/tree/master/examples/#2020-08-1602:05ericdalloHey borkdude, clojure-lsp is using clj-kondo and it's working nice, it's a nice integration 🙂 I think that it's just missing migrate the references implementation to use clj-kondo, but I'm not sure if we could do that use the analysis data#2020-08-1602:09ericdalloCurrently, when the server starts, clojure-lsp scan all the project with clj-kondo saving in the :cache-dir , I would like to know if we can use this data from all the project to get all references/usages on the project#2020-08-1602:10ericdallowith that, we can stop using https://github.com/snoe/clojure-lsp/blob/master/src/clojure_lsp/parser.clj#L1058-L1105`clojure-lsp`https://github.com/snoe/clojure-lsp/blob/master/src/clojure_lsp/parser.clj#L1058-L1105 and use kondo only#2020-08-1607:06borkdudeYou can with :output {:analysis true :format :edn}, and you can use that data. See the config page. Anakondo is a tool for emacs which also uses this approach #2020-08-1613:27ericdalloNice, I'll take a look, thanks!#2020-08-1912:51martinklepsch@borkdude I tried the updated hooks now and it’s a huuuuuge improvement 👏 Only last issue I’m having is that the docstring seems to be expected in the wrong place, according to the docs it should appear after the component name: https://p22.tr4.n0.cdn.getcloudapp.com/items/yAubDXb2/Image%202020-08-19%20at%202.50.45%20PM.png?v=ec0644f5c4dcb74d72953b01901f963c#2020-08-1917:55fiddlerwoaroof#2020-08-1917:55fiddlerwoaroofIs this lint message wrong?#2020-08-1917:55fiddlerwoaroofIt looks like clj-kondo doesn't recognize custom transducers#2020-08-1917:57borkdudeYeah. Made an issue for it here: https://github.com/borkdude/clj-kondo/issues/952#2020-08-1917:57fiddlerwoaroofCool, thanks#2020-08-1917:58borkdudeYou can override the type config, if it's bothering you enough right now#2020-08-1917:58fiddlerwoaroofIt's fine for now, this is in my "sandbox" project#2020-08-1917:56borkdude@martinklepsch What's a docstring?#2020-08-1917:56borkdude@martinklepsch Kidding. That's probably not too hard to fix. If you want, you can make an issue, or if you feel inclined, a PR#2020-08-1919:04lreadI thought you were glitching there for a second! simple_smile#2020-08-1919:05borkdudeIt was clickbait to seduce you to do a PR#2020-08-1919:10lreadNice marketing!#2020-08-2010:08borkdude@martinklepsch Fixed it on master#2020-08-2012:48lreadYay @martinklepsch! And thanks for letting me know, I have crossed it off my todo list! #2020-08-2112:15martinklepschThank youuuu! 🙌 I tried digging into the hooks DSL a little bit a few weeks ago and had a hard time getting started 😬 😅#2020-08-2112:17borkdudeHopefully more examples makes it easier. It surely helps if you have used rewrite-clj before#2020-08-2009:51borkdudeNice trick, you can tweak linter settings per language in a .cljc file by using conditionals:
(ns clj-kondo-cljs-macros.ns2.ns
  #?(:clj {:clj-kondo/config '{:linters {:unused-binding {:level :off}}}}))

(defn foo [x y]
  #?(:cljs x))
#2020-08-2012:35borkdudeIf anyone feels like adding clj-kondo to this page: https://analysis-tools.dev/tag/clojure, go ahead#2020-08-2016:22simonkatzAre these warnings wrong? If so, I can create an issue.#2020-08-2016:23simonkatzI get the following warnings:
src/main_ns.cljc:3:14: warning: namespace required-ns is required but never used
src/main_ns.cljc:5:17: warning: Unused private var main-ns/my-fun
The macro expansion has a use of my-fun and a use of the r alias, so I don’t think there should be any warnings.
#2020-08-2016:24borkdudeCan you please post the code as text? This is easier for me to try out#2020-08-2016:24simonkatzSure, give me a sec.#2020-08-2016:25simonkatzEither look at https://github.com/simon-katz/nomis-clj-kondo-cljc-macros-2 Or:
(ns required-ns)

(defn foo [] 42)
#2020-08-2016:25simonkatz
(ns main-ns
  #?(:cljs (:require-macros [main-ns :refer [my-macro]]))
  (:require [required-ns :as r]))

(defn ^:private my-fun [x]
  (inc x))

#?(:clj
   (defmacro my-macro []
     `(my-fun (r/foo))))
#2020-08-2016:26borkdudeI already see the problem. You are only using required-ns in Clojure. So why not wrap that in a #?(:clj ...)#2020-08-2016:26borkdudeNo wait, let me take another look ;)#2020-08-2016:27simonkatzThe expansion of the macro uses the req…. Oh, OK, I’ll wait 🙂#2020-08-2016:28simonkatzIf I run (my-macro), I get a result of 43 in both CLJ and CLJS, so I’m pretty sure that both my-fun and r/foo are used in both CLJ and CLJS.#2020-08-2016:34borkdude@nomiskatz It's an interesting edge case fore sure. You can fix it with a local config:
(ns main-ns
  {:clj-kondo/config '{:linters {:unused-private-var {:exclude [main-ns/my-fun]}
                                 :unused-namespace {:exclude [required-ns]}}}}
  #?(:cljs (:require-macros [main-ns :refer [my-macro]]))
  (:require [required-ns :as r]))
And feel free to post this edge case as an issue.
#2020-08-2016:34borkdudeI'm not sure if this is fixable since it depends on runtime usage of the macro if the namespace + private var will be really used.#2020-08-2016:35simonkatz@borkdude Thanks for confirming, and for the workaround. I’ll post an issue, but I understand why it might be a tough one.#2020-08-2017:09simonkatz(Done: https://github.com/borkdude/clj-kondo/issues/961)#2020-08-2114:24snoeI'm having difficulty figuring out if kondo will lint unresolved-symbols on required namespaces. I've got my cache updated, and I would expect str/bar to be unresolved.
(ns foo
  (:require [clojure.string :as str]))

(str/bar)
#2020-08-2114:47borkdude@snoe clj-kondo doesn't do that, to prevent false positives.#2020-08-2114:47snoeAnother question, is it possible for uneval #_ to follow the :skip-comments rule? This seems inconsistent to me, but maybe there's another flag I couldn't find.#2020-08-2114:50borkdudeThe idea here is that one usually evaluates code in a rich comment block, but #_ is just for eliminating code more easily than with ;;#2020-08-2114:53snoeRight, so when our team comments out code with #_ it's usually to keep that code around for a reason (otherwise we'd delete it), and the unused namespaces lints trigger, or signatures change and the commented block gets missed.#2020-08-2114:54borkdudewe could make that opt in I guess, with :lint-unevals or something.#2020-08-2114:47borkdudethere is an issue about it, could be an option I think (unresolved symbols of known namespaces)#2020-08-2114:48snoeI might take a look at it then. It seems with :exclude rules false positives could be eliminated per project#2020-08-2114:49borkdudehttps://github.com/borkdude/clj-kondo/issues/634#2020-08-2114:49borkdudeYes. Unresolved symbol linter could take fully qualified symbols I guess#2020-08-2817:42souenzzoDo kondo "evaluate"/"understand" clojure.spec in some way? can it lint things like
(s/def ::f (s/nilable fn?))
(let [{::keys [f]} env]
  (f))
You can'f call 'f' because it may be 'nil'
#2020-08-2817:51borkdude@souenzzo I'll paste something out of a conversation I had in #clojure-spec:
Slack: borkdude: Yes. spec is a runtime validation/conformation/generation library. And considering how complex core.typed gets, I don't think getting leverage out of specs at compile time is trivial. Using a tool for something it's not designed for in general is ... hard.

Slack: borkdude: I do think you can get <some> leverage out of it. E.g. a tool could inspect specs at runtime, parse out the trivial stuff like, is the first argument an int?? Then something like  can be generated and you will get <some> static analysis benefits for clj-kondo, for example.

borkdude: Malli / @ikitommi has demoed a similar approach at ClojureD.

jahvenni: Yeah, figuring out the trivial stuff is what I had in mind mostly. I can see many trivial cases where a linter utilising specs could easily provide value. Things like order of parameters, names of keyword arguments or tricky get-in's are mentally really heavy for someone who is used to have these things given by autofill. To me these sound like trivial things to check in most cases if spec is provided. It would be a much softer landing to a dynamic language.
#2020-08-2817:54ikitommi#2020-08-2817:54ikitommihere’s the prototype from clj-kondo + malli#2020-08-2818:19borkdudeJust merged support for linting in parallel which can give significant speedups when you are linting an entire classpath. https://github.com/borkdude/clj-kondo/issues/632#2020-08-2900:34snoeI'd like to start a thread about the possibility of adding the ability to go from a cursor position to an analyzer entry. Continuing https://github.com/snoe/clojure-lsp/pull/176#issuecomment-683123972#2020-08-2900:48snoeI imagine the difficulty comes in with macros, and the reticence is because linting may not need it? I think carve shows the utility of the analyzer itself, so I wonder if we think about other tools it could be a useful exercise. Renaming, I think, is right up there beside dead code for utility. A cli tool that could correct any inconsistent aliases, or rename a fully qualified var without resorting to sed and careful diff checking. Is it fair to want the analyzer to grow beyond kondo with some examples like this?#2020-08-2900:52snoeMy thinking is that kondo's analyzer feels like the closest thing we have to a tooling analyzer.#2020-08-2906:36borkdudeI think I'm fine with this, with the following caveats: 1) Some things are easier to lint while analyzing, this is why clj-kondo intertwines linting with analysis sometimes. So splitting an analyzer into a library is hard because of this. 2) I don't like clj-kondo linting getting slower because of extra work it has to do for other projects. The in-editor experience should be as fast as possible. So if we can prevent that, that's cool. I think we can accomplish that just using some configuration options.#2020-08-2906:39borkdudeBtw, carve uses clj-kondo analysis but then rewrites the code using rewrite-cljc, not using kondo. So it only uses the data output.#2020-08-2906:42borkdudeThere are some other issues that have to do with analysis here: https://github.com/borkdude/clj-kondo/issues?q=is%3Aissue+is%3Aopen+label%3Aanalysis#2020-08-2908:43borkdudeMaybe we can use the existing analysis hook or introduce new ones to be able to get other tooling to profit as well, in addition to the analysis info#2020-08-3000:55snoeI noticed that sometimes the (meta (:name %)) gives the position info, but not always... maybe we just need to make that more consistent.#2020-08-3015:01borkdudewhat is :name in this context?#2020-08-3114:13snoe@U04V15CAJ it's a mix of the analysis types, so var-usages seem to have meta on :name but on var-definitions and namespace-definitions and namespace-usages it is nil. I think if we always fill this in from rewrite-cljc I'd be able to use it for my purposes. Is it worth making an issue or do you foresee performance problems or difficulties with this approach?#2020-08-2906:25borkdudeSome exciting news! https://www.clojuriststogether.org/news/q3-2020-funding-announcement/#2020-08-2915:40practicalli-johnCongratulations, very much deserved#2020-08-2915:41borkdudeSame to you! :)#2020-08-2919:09jaihindhreddyDoes clj-kondo compile with the following java -version?
openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment GraalVM CE 20.2.0 (build 11.0.8+10-jvmci-20.2-b03)
OpenJDK 64-Bit Server VM GraalVM CE 20.2.0 (build 11.0.8+10-jvmci-20.2-b03, mixed mode, sharing)
#2020-08-2919:09borkdudeit should yes#2020-08-2919:10jaihindhreddyI just tried it, and got this error:
Error: Already registered: java.util.zip.ZipFile$CleanableResource.get(ZipFile, File, int)
com.oracle.svm.core.util.UserError$UserException: Already registered: java.util.zip.ZipFile$CleanableResource.get(ZipFile, File, int)
...
...
...
Error: Image build request failed with exit status 1
com.oracle.svm.driver.NativeImage$NativeImageError: Image build request failed with exit status 1
	at com.oracle.svm.driver.NativeImage.showError(NativeImage.java:1558)
	at com.oracle.svm.driver.NativeImage.build(NativeImage.java:1308)
	at com.oracle.svm.driver.NativeImage.performBuild(NativeImage.java:1269)
	at com.oracle.svm.driver.NativeImage.main(NativeImage.java:1228)
	at com.oracle.svm.driver.NativeImage$JDK9Plus.main(NativeImage.java:1740)
#2020-08-2919:10borkdudeAh 20.2, haven't tried it yet, currently using 20.1. But 20.2 should work#2020-08-2919:10borkdudeAaah#2020-08-2919:10borkdudeI know what this is. Just use 20.1 for now#2020-08-2919:10jaihindhreddySure. Thanks!#2020-08-2919:10borkdudeI'll upgrade soon#2020-08-2919:11borkdudeOr, if you feel like it, you can do it. The clojure reflector fix should be bumped to 20.2 in project.clj, but also other references in the CircleCI and Github config#2020-08-2919:12jaihindhreddythis, I assume: https://github.com/borkdude/clj-reflector-graal-java11-fix#2020-08-2919:12borkdudeyes#2020-08-2919:30jaihindhreddyWould you rather me make a PR directly, or make an issue first?#2020-08-2919:41jaihindhreddyWell, https://github.com/borkdude/clj-kondo/pull/979, but added diffs in resources/clj_kondo/impl/cache/built_in/clj/clojure.pprint.transit.json and resources/clj_kondo/impl/cache/built_in/clj/clojure.tools.reader.transit.json. Should I add these to .gitignore?#2020-08-2919:41jaihindhreddyalso, wow native-image takes a lot of RAM (to compile)!#2020-08-2919:58borkdudePlease don't add resources/* to .gitignore, it's essential to clj-kondo. Also, I wonder how did you end up with a diff in there, it's not relevant to the PR?#2020-08-2919:59borkdudeSo I would rather have you reset that file to the old one#2020-08-2920:03borkdudeYeah, GraalVM is quite heavy on the RAM, although for clj-kondo it doesn't go above 2 or 3GB I think?#2020-08-2920:13jaihindhreddy> So I would rather have you reset that file to the old one Done. > Please don't add resources/* to .gitignore, it's essential to clj-kondo. After reading docs/dev.md, I get this now. > Also, I wonder how did you end up with a diff in there, it's not relevant to the PR? Yeah, it's quite weird. I'm using clojure version 1.10.1.561. Not sure if that can make a difference. I'll see what the actual difference is.#2020-08-2920:17borkdudeThanks, merged!#2020-08-2920:50jaihindhreddyCourtesy of https://cljdoc.org/d/lambdaisland/deep-diff/0.0-47/doc/readme, I was able to find out the differences in the resources. clojure.pprint's cache had the following differences (Addition of :arities):
c-write-char {:col 1,
              :fixed-arities #{2},
              :name c-write-char,
              :ns clojure.pprint,
              :private true,
              :row 47,
              :top-ns clojure.pprint,
              +:arities {2 {:args (nil :nilable/int)}}},


p-write-char {:col 1,
              :fixed-arities #{2},
              :name p-write-char,
              :ns clojure.pprint,
              :private true,
              :row 360,
              :top-ns clojure.pprint,
              +:arities {2 {:args (nil :nilable/int)}}},
And clojure.tools.reader had the following:
read+string {:arities {0 {:ret :vector},
                       +1 {:ret :vector},
                       +2 {:ret :vector},
                       +3 {:ret :vector},
                       -:varargs {:min-arity 1, :ret :vector}}, ;; this got removed the the above 3 arities got added.
             :col 1,
             :fixed-arities #{0 +1 +2 +3},
             :name read+string,
             :ns clojure.tools.reader,
             :row 1008,
             :top-ns clojure.tools.reader,
             -:varargs-min-arity 1}, ;; this got removed as well.
Not sure why this is though. All three functions weren't changed in a long time.
#2020-08-2920:52borkdudeHave you ran any scripts locally that updated these files?#2020-08-2920:53jaihindhreddyI did run script/built-in. Should have mentioned this beforehand :man-facepalming:#2020-08-2920:53borkdudeI haven't ran those in a while. It could be that some logic related to that changed.#2020-08-2920:54borkdudeif you think the changes are correct, then we could add those as well#2020-08-2920:55jaihindhreddyYeah, https://github.com/clojure/tools.reader/blob/master/src/main/clojure/clojure/tools/reader.clj#L1009 never had a variadic arity. Seems like the new file is correctly identifying arities 0, 1, 2, 3.#2020-08-2920:55borkdudeI have a script, script/dump_types that dumps type information in a diff-able manner#2020-08-2920:56borkdudeSo when you run that on master and on your branch, it's easier to spot differences#2020-08-2920:56borkdudeIt could also be that one of the deps in clj-kondo got bumped, and the arities changed?#2020-08-2920:56jaihindhreddyGot it. Although, apart from having to read with transit, I don't think it's un-diffable#2020-08-2920:57jaihindhreddy> It could also be that one of the deps in clj-kondo got bumped, and the arities changed? I git-blamed those three functions, and they didn't change in years. So this is unlikely.#2020-08-2920:57borkdudethen clj-kondo must have had an error before#2020-08-2920:58jaihindhreddy:man-shrugging:#2020-08-2921:02borkdude@jaihindhreddy So I ran script/built-in and script/dump-types. Then made a branch: https://github.com/borkdude/clj-kondo/pull/980/files Now the diff is readable in Github, is what I mean
#2020-08-2921:04jaihindhreddyI get it now. Thanks for clarifying!#2020-08-2921:04borkdudeI'll just hook script/dump-types into script/built-ins, so we get it automatically#2020-08-2921:05jaihindhreddygood idea.#2020-08-2921:20borkdudeMerged. Also updated the script (since now babashka has had transit for a while).#2020-08-2921:22borkdudeIt's funny, you can also run that script using clojure script/dump_types.clj since all the deps are in deps.edn as well. But Clojure prints namespaced maps in script-mode it seems (https://clojuredocs.org/clojure.core/*print-namespace-maps*)#2020-08-2921:25borkdudeThis works: $ clojure -e "(set! *print-namespace-maps* false)" script/dump_types.clj#2020-08-3007:59jaihindhreddyWhat is the purpose of these https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/types/clojure/core.clj#L95 I see in the typing info?#2020-08-3008:04sogaiu@jaihindhreddy i noticed that for https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/types/clojure/core.clj#L1068 -- the 7886 matches the line number where tap> is defined in clojure core in a particular commit: https://github.com/clojure/clojure/blob/38bafca9e76cd6625d8dce5fb6d16b87845c8b9d/src/clj/clojure/core.clj#L7886#2020-08-3008:05jaihindhreddyRight! But those line numbers aren't static right? They can change over time. Are we then keeping these updated, if and when they change in clojure.core?#2020-08-3008:07sogaiuyes, i think you're right that those number aren't static. perhaps borkdude has some thoughts on this 🙂#2020-08-3009:41borkdudeThe clojure.core source doesn't change that often. It's just a reminder for me where I can find the original source#2020-08-3110:37robert-stuttafordthank you for fixing rum.core/defcs call-site arity issue @borkdude 🙏#2020-08-3121:02adambrosWhat are my options if I want to refer in my config.edn hooks to a rewrite that i want provided as a library or just in my home dir? can I refer to a hooks that is outside of the .clj-kondo directory? I'm using vim / ALE and clojure-lsp, but for ale i would have to write a whole new linter file to pass it --config, and clojure-lsp just doesnt support that currently...#2020-09-0606:17epi think you can pass --config-dir to point to another directory#2020-08-3121:07borkdudeCurrently hooks are expected to be inside the .clj-kondo. directory. Does a symlink work for your situation?#2020-08-3121:08adambrosi guess it would work, i was just hoping to have a home dir kondo config directory that would always be applied to all my clojure projects (or something equivalent)#2020-08-3121:09borkdudeWe don't. Clj-kondo has the opinion that such config belongs to a project and that all team members agree on the same config#2020-08-3121:10adambrosok, but does that mean that I would have to copy paste any hooks related to a library?#2020-08-3121:11borkdudecurrently yes#2020-08-3121:11adambrosat the very least, if i could put some hooks into a library, and then use it in each project that would work fine#2020-08-3121:12borkdudewe might do better here by providing a classpath option, so you can put your hooks in a github project and use clojure to resolve that library into a classpath#2020-08-3121:12adambrosthat could work#2020-08-3121:13borkdudeCould you make an issue about this?#2020-08-3121:14adambrossure, not sure when but i'll get to it this week#2020-08-3121:14borkdudethanks!#2020-08-3121:34adambrosfrom the looks of it there are a few issues already related to this, eg: https://github.com/borkdude/clj-kondo/issues/559 you sure you want me to make a whole new issue? I could just add a comment?#2020-08-3121:41borkdudeI guess it is related#2020-08-3121:43borkdudeso posting the idea there is ok with me#2020-09-0213:26borkdudeI'd like to get started on this feature soon: https://github.com/borkdude/clj-kondo/issues/872 Ignoring a warning from clj-kondo on one form at a time. If you have any input on this, feel free to join the discussion.#2020-09-0214:31sogaiusome of the code in here: https://github.com/sogaiu/adorn adds inline defs to functions -- along with metadata. it might be relatively easy to adapt / copy-modify the code there to make editor support for adding the "markings" that you decide upon.#2020-09-0214:39borkdudeRight now I'm thinking of: ^:clj-kondo/ignore for ignoring every warning/error in form. And ^{:clj-kondo/ignore [:invalid-arity]} for ignoring specific linter warnings. Possibly support for fine-grained config: ^{:clj-kondo/config {:linters {:unresolved-symbol {:level :warning}}}} on forms, although I think that's a bit of a stretch and too verbose for this purpose.#2020-09-0215:20sogaiuthose seems sensible. curious whether one could use aliased keywords to shorten things somehow. i guess not without making an alias...#2020-09-0215:32borkdudeWe could also do ^:ignore but that would maybe conflict with other tools#2020-09-0307:49borkdudeUpdated proposal regarding the above issue about ignoring warnings: https://github.com/borkdude/clj-kondo/issues/872#issuecomment-686315535#2020-09-0312:48robert-stuttafordany chance of a new release soon, @borkdude? 🙂 keen to get that rum fix into general circulation here at Cognician#2020-09-0312:48borkdude@robert-stuttaford The Rum fix is entirely done in user space#2020-09-0312:48borkdudeno need for a release#2020-09-0312:48robert-stuttafordoh!#2020-09-0312:48robert-stuttafordi'll do my homework, thanks+sorryforthenoise#2020-09-0312:49borkdudeNo problem! I'm glad it can be done in user space, since I got another report about it: https://github.com/borkdude/clj-kondo/issues/987 Multi-arity components...#2020-09-0312:50borkdudeIf anyone feels challenged to pick it up, be my guest, else I'll get to it after some other stuff#2020-09-0312:50robert-stuttafordgosh how did i miss that 😊:face_palm:#2020-09-0312:51borkdudeReally no problem :)#2020-09-0312:52robert-stuttafordomg omg it works yay#2020-09-0312:52robert-stuttafordthink of me when you have that next sponsored coffee thing, haha#2020-09-0312:54borkdudeI will tomorrow, thanks for sponsoring ;) Hopefully there will be a release somewhere in the middle of this month, featuring this new thing: https://github.com/borkdude/clj-kondo/issues/872#issuecomment-686315535 If you have any ideas about it, there's still time#2020-09-0313:00robert-stuttafordvery interesting! i don't have anything of value to add. we live with our linting errors, but clean them up as we work through old places#2020-09-0313:00borkdudesame here on my work projects#2020-09-0314:26robert-stuttaford@borkdude do you perhaps have any guidance / writing on integrating kondo into a clojure app (e.g. a web app) to lint EDN editors inside CMSes? so basically https://clj-kondo.michielborkent.nl/ but with the server side using kondo-in-jvm-clojure instead of shelling out to the bb version?#2020-09-0314:27robert-stuttafordwe can't be the first ppl to do this, i'm thinking!#2020-09-0314:27borkdudethat front-end is shelling out to the clj-kondo binary, it has nothing to do with bb, but I get the point: shelling out.#2020-09-0314:28borkdudeWell, you could use clj-kondo JVM in your server and just send the lint information back to the front-end?#2020-09-0314:28borkdudebasically the same, but just using the JVM, not shelling out#2020-09-0314:29borkdudeThe source code is here: https://github.com/borkdude/clj-kondo.web#2020-09-0314:29borkdudeI used CodeMirror, but there are also alternatives to this. I was just familiar with that one, it has a linting plugin to display warnings#2020-09-0314:29robert-stuttafordyeah super happy to use that#2020-09-0314:30robert-stuttafordfound the jvm api doc nice#2020-09-0314:31borkdudeyeah, should also be on cljdoc: https://cljdoc.org/d/clj-kondo/clj-kondo/2020.07.29/api/clj-kondo.core#2020-09-0314:31borkdudeI see I forgot a {:no-doc} in an impl namespace :)#2020-09-0314:32borkdude@robert-stuttaford If you want something lighter weight than clj-kondo, you might also want to look at edamame#2020-09-0314:32borkdudehttps://github.com/borkdude/edamame#2020-09-0314:33borkdudeit spits out location data also on error, in an ex-info#2020-09-0314:33robert-stuttafordahhh that might be all we need, because it's only EDN we need to lint#2020-09-0314:34robert-stuttafordwell kondo will give a list of all the linting issues right, which we can then send back for codemirror to display#2020-09-0314:35borkdude@robert-stuttaford
user=> (require '[edamame.core :as e])
nil
user=> (e/parse-string "{")
Execution error (ExceptionInfo) at edamame.impl.parser/throw-reader (parser.cljc:89).
EOF while reading, expected } to match { at [1,1]
user=> (ex-data *e)
{:type :edamame/error, :row 1, :col 2}
#2020-09-0314:35borkdudeThat's true, edamame will just stop parsing on error.#2020-09-0314:36robert-stuttafordright#2020-09-0314:36borkdudewe could also build that into edamame probably, I haven't really given it much thought yet#2020-09-0314:38borkdudeyou could also use both, since you can also verify a valid EDN structure according your own rules and give extra lint warnings if it doesn't conform to your specs for example#2020-09-0314:38borkdudeedamame attaches location information where possible#2020-09-0314:39borkdudethere's also a mode to return different kinds of nodes instead of numbers and strings, so you can still have location info for those as well#2020-09-0314:40borkdudeThere's also a docker image for clj-kondo: you might get away with using that instead of the binary on the server as well. Anyway, plenty of ideas :)#2020-09-0314:43robert-stuttafordthanks dude!#2020-09-0315:39borkdude@robert-stuttaford Note that you can lint strings using (with-in-str "(+ :foo)" (clj-kondo/run! {:lint ["-"]}))#2020-09-0316:12robert-stuttafordsweet thank you, that's what we'll probably end up doing!#2020-09-0320:56borkdudeLittle update: https://github.com/borkdude/clj-kondo/issues/872#issuecomment-686760114#2020-09-0410:07sogaiuso i'm trying to build master as well as the ignore-form branch, but it seems i'm doing something wrong. i'm using the jdk 11 20.1.0 version of graal on linux -- bash script/compile gives me this: https://pastebin.com/uJZNZKFF i noticed that the build.md doc now mentions something about using jdk12 to update resources: https://github.com/borkdude/clj-kondo/blob/master/doc/build.md#optional-steps is that something i need to do to build from source now?#2020-09-0410:09borkdudeIt's been upgraded to 20.2.0 now#2020-09-0410:10sogaiuso are you saying i must use 20.2.0? i'm fine to do so.#2020-09-0410:10borkdudeThe optional steps are optional, so don't bother with those#2020-09-0410:10borkdudeyes#2020-09-0410:10sogaiuok, thanks!#2020-09-0410:10borkdudeWe should mention 20.2 in that README#2020-09-0410:10borkdudeit also has to be java11 now#2020-09-0410:11borkdudePR welcome!#2020-09-0410:11borkdudeWe can only run with one specific GraalVM version due to the reflector fix#2020-09-0410:11sogaiuok -- gotta go out for a bit, but when i get back i'll try the steps and update the docs if i'm successful 🙂#2020-09-0411:36sogaiuok, 20.2.0 seemed to be enough -- PR with doc update suggestion sent#2020-09-0411:40sogaiu@borkdude so i tried the ignore-form branch. the basic functionality seems to work :thumbsup: i don't know if i did something wrong, but the following seemed to also affect linting:
(let [x 1]
  {:clj-kondo/ignore [:redundant-let]}
  (let [y 2]
    (inc x y)
    ))
$ ./clj-kondo --lint ignore-form.clj
ignore-form.clj:4:5: error: clojure.core/inc is called with 2 args but expects 1
linting took 17ms, errors: 1, warnings: 0
note: i left off the discard marker #_
#2020-09-0411:41sogaiuwhen i comment out the map, the linting goes back to normal#2020-09-0411:42sogaiu
(let [x 1]
  ;;{:clj-kondo/ignore [:redundant-let]}
  (let [y 2]
    (inc x y)
    ))
$ ./clj-kondo --lint ignore-form.clj
ignore-form.clj:3:3: warning: Redundant let expression.
ignore-form.clj:4:5: error: clojure.core/inc is called with 2 args but expects 1
linting took 7ms, errors: 1, warnings: 1
#2020-09-0411:57borkdudeOh, that's weird!#2020-09-0411:58borkdudeI'll log this as an issue to fix#2020-09-0411:58sogaiuah so does it happen for you?#2020-09-0411:58borkdudeyes#2020-09-0411:58sogaiuok thanks#2020-09-0411:58borkdudeoh hmm, no this is intended, since the map makes the let not be redundant anymore ;)#2020-09-0411:59sogaiulol#2020-09-0411:59sogaiuhadn't thought of that 🙂#2020-09-0413:39borkdudeInput welcome on having multiple config dirs for shared config/hook code: https://github.com/borkdude/clj-kondo/issues/992#2020-09-0421:09borkdude^ What if the Rum library hook config was part of the Rum library itself and clj-kondo could read it from your classpath?#2020-09-0511:06borkdudeI think that issue now mostly looks good. One thing I'm grappling with is how can we have :config-paths in a way that it will work for all users on a project, be it on Windows, mac, Linux, CI. I was thinking we could have some env var interpolation and conditional logic:
["%HOME%/.clj-kondo"  [:when %CI% "/home/deploy/kondo-configs"]]
:-s, but probaaably not
#2020-09-0511:08borkdudeSilently ignoring non-existing paths probably also works. Not sure about Windows paths combined with Linux paths#2020-09-0511:08borkdudeMaybe Windows users should write: "/C/Users/borkdude/.clj-kondo"#2020-09-0511:11borkdudeNeh, I guess they are fine with just writing "C:\\Users" since this works both on linux and Windows: (.exists (io/file "C:\\Users")) ;;=> false#2020-09-0511:14borkdudeProbably in a team, relative paths are quite common: just put all the shared configs in a dir one or two up#2020-09-0513:34lreadTidbit that may be helpful or not: I think I am remembering correctly, that within the JVM, forward slashes also work on Windows.#2020-09-0513:36borkdudeLet me verify that. What I did test is that classpath entries / resources are valid with forward slashes only#2020-09-0513:37borkdudeIt's so convenient that I can just ssh into my new Windows computer and do:
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "aeccc1dcc5cadbcacbeeeaebfde5fae1fe83e4e09cfbe0faf8"}, :content ("[email protected]")}
to spin up a Windows Clojure REPL ;)
#2020-09-0513:37borkdudeYep, it works:
user=> (.exists (io/file "C:/Users"))
true
#2020-09-0513:37borkdudethanks#2020-09-0513:38lreadOddly though, I think classpath separators are not automatically translated.#2020-09-0513:38borkdudeI'll just not use those#2020-09-0514:07borkdudeI guess this is a little bit iffy when on macOS/linux:
user=> (.isAbsolute (io/file "C:/Users"))
false
user=> (.isAbsolute (io/file "C:\\Users"))
false
#2020-09-0514:45borkdudeSo here is the idea in a screenshot:#2020-09-0514:46borkdude@robert-stuttaford @martinklepsch Would also appreciate your feedback since you use the Rum hook code (potentially in multiple projects) - the issue: https://github.com/borkdude/clj-kondo/issues/992#2020-09-0515:16robert-stuttaford@borkdude yes, this is great - we have a repo we put all our developer machine stuff in, adding this along side ~/.clojure/deps.edn and ~/.m2/settings.xml would be great!#2020-09-0609:37borkdudeIf you would like clj-kondo to resolve config and hook code from ~/.clj-kondo, or other locations, please leave a message here: https://github.com/borkdude/clj-kondo/issues/992 Since I'm getting cljtogether funding, now is a good time to leave feedback so we can make some progress on this.#2020-09-0711:44borkdudeclj-kondo on master will now resolve config from ~/.config/clj-kondo and respect XDG_CONFIG_HOME#2020-09-0716:38robert-stuttafordwonderful! you need to cut a release for it to be available via homebrew right?#2020-09-0716:51borkdudeyes, but you can download binaries from CircleCI builds or Github builds as well#2020-09-0717:11robert-stuttaford👍#2020-09-0717:36borkdudeI hope to release at the end of this week #2020-09-0716:53borkdudeLittle experiment with emitting runtime spec information to a config file which clj-kondo uses for type info: https://gist.github.com/borkdude/c0987707ed0a1de0ab3a4c27c3affb03#2020-09-0815:50borkdudeFollow up idea on #992: https://github.com/clj-kondo/clj-kondo.configs/blob/master/README.md#installation#2020-09-0820:02borkdudeI'm currently (re)searching a solution to the following: Clj-kondo will support :config-paths in the next release which is a list of directories with additional config. This opens up the possibility of a tool that scans your classpath for library specific clj-kondo configs, spits them out to directories in .clj-kondo, so clj-kondo can pick up on those. What should be the directory structure in which libs bundle their clj-kondo config? E.g. a library repo could have:
resources/clj-kondo-config/rum/rum/config.edn
resources/clj-kondo-config/rum/rum/hooks/*.clj
and a tool would scan the classpath, detect all the clj-kondo/*/* directories, spit them out to:
$project/.clj-kondo/configs/rum/rum/config.edn
$project/.clj-kondo/configs/rum/rum/hooks/*.clj
and clj-kondo will implicitly add configs/*/* to the :config-paths. If anyone sees a problem with this or has other ideas, I'd like to hear them. This is for #992.
#2020-09-0820:04borkdude(this tool can then become part of your normal dependencies, much like a lein plugin, or deps.edn alias tool)#2020-09-0903:37sogaiuthat's this issue, right? https://github.com/borkdude/clj-kondo/issues/992#2020-09-0905:52borkdudeCorrect #2020-09-0913:30borkdudecutting a new release... https://github.com/borkdude/clj-kondo/blob/master/CHANGELOG.md#v20200909 parrot#2020-09-0913:55borkdudeDone, 2020.09.09 released. Have fun! :)#2020-09-0915:12dominicmCurious to know if you measured performance for parallel linting and how it went?#2020-09-0915:12dominicmI guess CI will benefit mostly?#2020-09-0915:27borkdudeI did measure. Depending on your CPU you can see speed-ups of several factors. This has no impact on linting just one file, it's only beneficial when linting a classpath (e.g. to populate your cache).#2020-09-0921:05dominicmGotta get that thread ripper in play eh#2020-09-0921:09borkdudeYeah, but even on my 8-core macbook pro it's noticeable. On my dual-core Macbook Air far less.#2020-09-0921:09borkdudeI don't have a thread ripper btw, just one model cheaper than that#2020-09-0921:09borkdudeMy colleague does#2020-09-0922:22dominicmHere I am on my old fx8350 😀#2020-09-0919:39borkdudehttps://github.com/clj-kondo/inspector#2020-09-1021:18borkdudeToday two configs were contributed to https://github.com/clj-kondo/config, one for claypoole and one for mockery (which I had never heard of).#2020-09-1021:23lreadAwesome!#2020-09-1105:01sogaiunice to have more examples. @lee am finding yours to be particularly instructive, thanks 🙂#2020-09-1105:27sogaiui'm looking at examples of tweaking behavior of :unresolved-symbol here: https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/config.clj#L42-L53 it looks like by using :exclude, one can ignore instances globally or within the context of a specific call (or calls). i don't suppose it's possible to ignore instances within specific files... the use case is when there is a file that has no ns form and is using in-ns instead, e.g. clojure's core_deftype.clj, core_print.clj, core_proxy.clj, etc. is there some good way to have the unresolved symbol errors turned off only within those files without modifying them? (i'd rather not turn off the unresolved symbols linting for specific symbols across all of clojure's source if possible.)#2020-09-1106:48borkdude@sogaiu you can ignore files in the output but that will ignore the entire file #2020-09-1107:09sogaiuok thanks#2020-09-1107:24borkdude@sogaiu Maybe it might sense to also allow namespace local config in config.edn under :namespaces {clojure {pprint {:linters {...} :lint-as {}}}}#2020-09-1107:29borkdudebut this is generally only useful for sources you don't control#2020-09-1107:29borkdudeon the other hand, it might be nice if you don't want to have your config in the source#2020-09-1107:33sogaiuthat sounds interesting -- perhaps it can be noted as a future possibility. if there are other requests for it may be it can be revisited.#2020-09-1107:35borkdudeI'm also thinking about this in the context of REPL-assisted static analysis like https://github.com/clj-kondo/inspector. Right now it only dumps types for the :type-mismatch linter but we could have like a reverse analysis output format that clj-kondo can take in for linting.#2020-09-1107:41borkdudehttps://github.com/borkdude/clj-kondo/issues/1004 https://github.com/borkdude/clj-kondo/issues/1005#2020-09-1108:36sogaiu@borkdude i don't see the connection yet, but hopefully will get it in a bit 🙂 btw, regarding hooks and handling macros, have you had a look at colinfleming's 2015 conj talk: https://www.youtube.com/watch?v=kt4haSH2xcs ?#2020-09-1108:40borkdudeI've seen it yes#2020-09-1108:40sogaiuok, was curious as it has some mention of parsing macros.#2020-09-1108:41sogaiuthere is this repository that he released after too: https://github.com/cursive-ide/error-test#2020-09-1108:41borkdudethe connection between those two issues is: inform clj-kondo about vars in your namespace. either by suppressing things or really telling it what's there#2020-09-1108:42sogaiuah ok, thanks for the explanation.#2020-09-1108:43borkdudeI've considered that approach, and implemented a sexpr-based solution initally, but that didn't work since not all things can carry location metadata. So preserving the rewrite-clj nodes is better for linting and having a full Clojure environment for transforming those nodes is far more powerful than some DSL#2020-09-1108:44borkdudeWe can still add clojure spec to the hooks API if you want to do validation on the sexpr directly#2020-09-1108:45sogaiuah, too bad that didn't work out. i guess if it means i get my real-time notification from clj-kondo, the being tied to rewrite-clj is a trade-off i'm ok with. (ofc, i am a rewrite-clj* fan 🙂 )#2020-09-1108:46borkdudeThe hooks API is rather thin, so switching to some other solution than rewrite-clj might still be possible in the future (but I doubt it)#2020-09-1108:47sogaiuok -- well, i doubt i'll come up with anything useful, but a non-library specific approach has some application to other tooling so i'm interested in other ideas.#2020-09-1108:47borkdude#lsp has a DSL for it#2020-09-1108:47borkdudebut they're switching to clj-kondo now for linting and possibly also analysis#2020-09-1108:48borkdudeI think they ran into some edge cases which couldn't be expressed in the DSL (@snoe)#2020-09-1108:49sogaiuah i didn't know about the lsp dsl thing -- thanks for the tip.#2020-09-1108:50borkdudewe can still support something like that as an easier thing instead of hooks which then writes the lower level hooks code for you#2020-09-1108:51borkdudeone benefit of hooks is also that you can emit custom warnings based on your macro input#2020-09-1108:51borkdudethere's already examples of this in the config repo#2020-09-1108:51sogaiuyes i saw that -- looks cool.#2020-09-1108:51sogaiui have been studying the examples and trying to make something for defdirectives in clojure's source#2020-09-1108:53borkdudeI want to add predicates api/vector?, api/symbol? etc so people rely less on api/sexpr which can be a footgun#2020-09-1108:53sogaiuin emacs-lisp, to get edebug to work with macros they have this way for macro definitions (i think) to express info about how to understand them: https://www.gnu.org/software/emacs/manual/html_node/elisp/Specification-List.html#Specification-List#2020-09-1108:53sogaiuyeah, that makes sense#2020-09-1108:53sogaiui'm sure lread will be happier to see sexpr used less#2020-09-1108:55sogaiuthis rewrite-cljc-playground issue is related, right? https://github.com/lread/rewrite-cljc-playground/issues/5#2020-09-1108:56borkdudehttps://github.com/borkdude/clj-kondo/issues/1006#2020-09-1108:56borkdudeAh yes, thanks#2020-09-1108:58borkdudeInitially in the hooks API I called api/sexpr on the node, while also adding location as metadata. So people could write hooks directly on the sexpr. After transformation I printed this to a string including metadata and then read this in again using rewrite-clj#2020-09-1108:59borkdudeIt works for a lot of the code, but not when you had expressions like (inc 1) in your macro arguments#2020-09-1109:00borkdudeThat's mostly why I abandoned that approach#2020-09-1109:00borkdudeelse you could have almost used your macro as is for expansion#2020-09-1109:03sogaiuthe current approach sounds safer#2020-09-1109:04sogaiui need to think a lot more about this -- was mostly curious about background. sorry i was so late to the party 🙂#2020-09-1109:05borkdudeno problem. I think it's pretty cool that we can now run a Clojure interpreter in a binary version of clj-kondo :)#2020-09-1109:05sogaiuyes, i thought was pretty neat too!#2020-09-1109:35sogaiu@borkdude so i don't see map-node here: https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/hooks.clj is that something that would be ok to add? or may be it's available some other way?#2020-09-1109:36borkdudeI think we could add that, but so far I've often found other ways of dealing with this#2020-09-1109:37borkdudemaybe you could give the example#2020-09-1109:37borkdudeof what's the input and how you are rewriting it#2020-09-1109:37sogaiuhttps://gist.github.com/sogaiu/2be50c906e52a686699c154d4423c91d#file-gistfile1-txt-L25-L44#2020-09-1109:38sogaiuso defdirectives i think is supposed to expand to:
(def directive-table {,,,})
#2020-09-1109:38borkdudewhy is it important that you expand exactly like that macro#2020-09-1109:38borkdudeclj-kondo doesn't do anything with that right#2020-09-1109:39sogaiulol -- no idea actually. may be it will be fine to do just (def directive-table nil)?#2020-09-1109:39sogaiuhappier to do less work 🙂#2020-09-1109:40borkdudeI would probably do this:
(defdirectives
  (\A
   [:mincol [0 Integer]
    :colinc [1 Integer]
    :minpad [0 Integer]
    :padchar [\space Character]]
   #{:at :colon :both}
   {}
   #(format-ascii print-str %1 %2 %3))
  )

;; =>

[[\A
  [:mincol [0 Integer]
   :colinc [1 Integer]
   :minpad [0 Integer]
   :padchar [\space Character]]]
 #{:at :colon :both}
 {}
 #(format-ascii print-str %1 %2 %3)]
#2020-09-1109:40borkdudeit's important that all usages are still visible to clj-kondo#2020-09-1109:40borkdudeelse you'll get warnings about unused imports, etc.#2020-09-1109:41sogaiui think i get what you're saying -- though perhaps it's sensible to wrap the bottom thing in a def form?#2020-09-1109:41borkdudesure#2020-09-1109:41sogaiuok, i'll give that a try. thanks!#2020-09-1109:42borkdudethat's one of the 💡 in writing hooks: you don't have to conform to the semantics of the original macro at all#2020-09-1109:46sogaiuyes, i was noticing that in lread's example but i guess there were two parts of my brain that weren't communicating well 🙂#2020-09-1109:46sogaiushould make things faster#2020-09-1109:47borkdudethere's also a time macro to measure performance#2020-09-1109:51sogaiuthanks for the tip#2020-09-1110:43sogaiu@borkdude ok, your suggested approach is mostly working out. there is one type of thing though that seems to lead to warnings: https://github.com/clojure/clojure/blob/master/src/clj/clojure/pprint/cl_format.clj#L1373-L1379 those bits get wrapped in a fn form -- https://github.com/clojure/clojure/blob/master/src/clj/clojure/pprint/cl_format.clj#L1326 using a list-node with a fn token node and a vector followed by the form to wrap seems to work ok. does that sound sane?#2020-09-1110:44borkdudevery#2020-09-1110:45borkdudewhat kind of warning did you get?#2020-09-1110:52sogaiuone example is:
src/clj/clojure/pprint/cl_format.clj:1375:22: error: unresolved symbol params
#2020-09-1110:52sogaiui think that corresponds to: https://github.com/clojure/clojure/blob/master/src/clj/clojure/pprint/cl_format.clj#L1375#2020-09-1110:59borkduderight, so it expects some fixed set of named args it seems. someone went really wild with their macros there..#2020-09-1111:06sogaiuha ha ha#2020-09-1111:06sogaiui think with this, the number of errors when linting cl_format.clj are reduced: https://gist.github.com/sogaiu/2be50c906e52a686699c154d4423c91d#2020-09-1111:07sogaiui guess cl_format.clj is from a long while back -- it has defstruct#2020-09-1111:08borkdudeabout 20 lines of code, doesn't seem that bad: https://gist.github.com/sogaiu/2be50c906e52a686699c154d4423c91d#file-defdirectives-clj-L80-L99#2020-09-1111:08sogaiuthanks to your tip!#2020-09-1115:28borkdudeRum hooks for defc and defcs now support multi-arity definitions at https://github.com/clj-kondo/config#2020-09-1118:28borkdudeCool, someone wrote a hook to suggest turning long ->> chains into transducer equivalents: https://github.com/borkdude/clj-kondo/issues/323#issuecomment-691247062#2020-09-1211:22svtI there any way to fix the errors given by clj-kondo via command??#2020-09-1211:24svtI’m working on a project and previously it didn’t had clj-kondo and after adding clj-kondo we found 300+ issues with code. Fixing all of them manually will be pain and time consuming. Is there any other way you can suggest??#2020-09-1211:29borkdude@cksharma122 There are several ways to deal with this. I think the easiest one is spitting out the warnings to a file and then diff with that file the next time#2020-09-1211:30borkdudeAnd there are plenty of ways to configure clj-kondo, if you want to disable some rules for now: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#2020-09-1211:30borkdudeReviewdog is one of the tools that can do this diffing as well: https://github.com/reviewdog/reviewdog but I've never used it.#2020-09-1211:31borkdudeAnother way is using EDN output and then do some scripting on top of that (possibly using babashka)#2020-09-1211:31borkdudeHope that helps.#2020-09-1211:33svtThanks you @borkdude I’ll try these options#2020-09-1212:53nivekuildoes it make sense to have a lint for get-in used only to extract keywords/functions? It seems like it's just strictly better to use -> for those, being faster and less syntactically noisy#2020-09-1212:56borkdude@kevin842 Feel free to post an issue about this so people can discuss. I think an opt-in linter could work. Also, I think you can write a thing like this yourself now using hooks. Example: https://github.com/borkdude/clj-kondo/issues/323#issuecomment-691247062#2020-09-1213:01borkdudeWe already have a related linter, single-key-in, which warns if you use get-in and assoc-in and update-in with a vector with a single key in it#2020-09-1213:04borkdudeI guess you would then get two warnings about (get-in x [:foo]) - hmm, no, it only should suggest -> when you have more than one key#2020-09-1309:09borkdudeDoes anyone using flycheck-clj-kondo want to take a look at this PR? https://github.com/borkdude/flycheck-clj-kondo/pull/10#2020-09-1309:11sogaiui don't use cider, but the actual code doesn't look like it is tied to cider. does that seem right?#2020-09-1309:13borkdudethat's right#2020-09-1309:13sogaiuok, i'll take a look then#2020-09-1309:15borkdudethanks!#2020-09-1310:11sogaiu@borkdude ok, i've looked and tested a bit. i'd like to confirm that i understand the background of the situation. iiuc, in its current state, when one sends .cljc content to clj-kondo via stdin, using --lang clj or --lang cljs is likely to fail if there are any reader conditionals. does that sound right? so when using cider, there can be two repl connections, one to a clj repl and another to a cljs repl. i guess based on the current major-mode, which repl is used for evaluation is determined. so flycheck-clj-kondo also looks at the major mode to decide what value to use as the value for --lang. but this is a problem for .cljc content because if one is switched to either clojure-mode or clojurescript-mode, --lang will end up being passed clj or cljs, basically making it likely that clj-kondo cannot cope, getting something typically like this:
<stdin>:0:0: error: Can't parse <stdin>, Unparsable namespace form
#2020-09-1310:12borkdudetrue#2020-09-1310:12sogaiuok, so i think this pr tries to cope with this.#2020-09-1310:12sogaiuit provides a buffer local variable that overrides things -- one can set it to "cljc".#2020-09-1310:14borkdudeThat's right. I wondered about the use of eval, if this was legitimate there#2020-09-1310:14sogaiuhe he -- i am not so sure either.#2020-09-1310:14sogaiuthere is some other refactoring too which i wondered whether was necessary.#2020-09-1310:33sogaiu@borkdude so i tried modifying the code a bit -- pulling the command construction back out into a let like before and not using eval. you might have guessed this, but that doesn't seem to work. may be it is because the value of flycheck-clj-kondo-lint-lang is then captured at macro compile time and consequently what one sets it to later is not reflected when constructing the command line to execute. does that sound plausible?#2020-09-1310:34borkdudeyes.#2020-09-1310:35borkdudemaybe the macros can all be turned into functions?#2020-09-1310:36sogaiui can investigate that#2020-09-1310:51sogaiufwiw, it appears that using eval within the context of :command is a thing: https://github.com/flycheck/flycheck/issues/1515 this issue had to do with extending that to work for the first part of :command -- the one place it didn't (doesn't) work. which is not our case.#2020-09-1311:06sogaiu@borkdude i'm not sure i quite follow about turning macros into functions. i did find that there is a function alternative (https://github.com/flycheck/flycheck/blob/master/flycheck.el#L5681) to the macro flycheck-define-checker, but i'm not sure how using that would help here. however, as far as constructing the command is concerned, there might be an alternative to using eval. i found a list here of the kinds of things one can use when constructing an arg for the command: https://github.com/flycheck/flycheck/blob/master/flycheck.el#L5899 (eval FORM) is one of the listed options, but there are also things like: https://github.com/flycheck/flycheck/blob/master/flycheck.el#L6002-L6004#2020-09-1311:08borkdudeooh option-flag might be what we want here#2020-09-1311:08sogaiuam looking for example usages#2020-09-1311:19sogaiuhttps://github.com/favadi/flycheck-gometalinter/blob/master/flycheck-gometalinter.el#L101-L113#2020-09-1311:20sogaiuhttps://github.com/weijiangan/flycheck-golangci-lint/blob/master/flycheck-golangci-lint.el#L79-L88#2020-09-1311:20sogaiuhttps://github.com/purcell/flycheck-ledger/blob/master/flycheck-ledger.el#L44-L53#2020-09-1311:20sogaiugo https://grep.app#2020-09-1311:21sogaiuwill give it an attempt now#2020-09-1311:21borkdudecan we accomplish the desired behavior with that?#2020-09-1311:24sogaiu@borkdude hmm, i think we want to fall back to lang if there is no value defined for flycheck-clj-kondo-lint-lang. i am not sure if option-flag will be enough.#2020-09-1311:25borkdudeoption-flag takes not a default?#2020-09-1311:26sogaiuit doesn't look like it to me. may be i misunderstood?#2020-09-1311:27sogaiufwiw, when searching for uses of option-flag i did find that it wasn't uncommon for flycheck things to be using eval.#2020-09-1311:27borkdudeok, maybe it's alright then#2020-09-1311:28sogaiuso we have done due diligence at least 🙂#2020-09-1311:29borkdudeyes, thanks for the review!#2020-09-1311:29sogaiunp!#2020-09-1311:30borkdudeMaybe a bit bikesheddy, but maybe flycheck-clj-kondo-lang is a better name than flycheck-clj-kondo-lint-lang#2020-09-1311:31sogaiui did think the lint-lang version was a bit on the long side#2020-09-1311:32sogaiuotoh this is emacs lisp 😛#2020-09-1311:32borkdudeI left a comment.#2020-09-1311:32borkdudeit's emacs lisp, but also kondo which emphasizes cleaning up things you don't need ;)#2020-09-1311:33sogaiuha ha ha -- good point#2020-09-1706:12robert-stuttafordwe've hit a snag that i'm not sure how best to solve. we use kondo as a library in our app, using :mvn/version "2020.09.09", and we also have carve in our ~/.clojure/deps.edn. so now, we can't carve our code because of this issue:
Error building classpath. Unable to compare versions for clj-kondo/clj-kondo: {:git/url "", :sha "f5e6c35ffaae2f5c7945887d5a124872b32db4c3", :deps/manifest :deps, :deps/root "/Users/robert/.gitlibs/libs/clj-kondo/clj-kondo/f5e6c35ffaae2f5c7945887d5a124872b32db4c3"} and {:mvn/version "2020.09.09", :deps/manifest :mvn}
#2020-09-1706:13robert-stuttafordi guess we'd have to switch to a git sha for our dep, and that'd solve it, but it does raise an interesting issue!#2020-09-1706:55borkdude@robert-stuttaford isn't that what aliases are for?#2020-09-1706:56borkdudeclojure -A:carve ..., clojure -A:clj-kondo ...#2020-09-1707:00borkdudeah sorry, you are using clj-kondo in your app. hmm. I think it's an interesting point discussing in #tools-deps#2020-09-1707:11borkdudeas a workaround you might indeed want to use the same git SHA as 2020.09.09#2020-09-1707:11borkdudeI could also make a clojars release of carve if it's really an annoying thing#2020-09-1707:14robert-stuttafordyes, that's what i did, switched to git sha#2020-09-1820:06dharriganOften, I have rich comment blocks that have blocks of vars that I redefine, to try things out (i.e., for different environments). Currently clj-kondo says this warning: redefined var#2020-09-1820:06dharriganIs there a way to ignore that for an entire function block?#2020-09-1820:07dharriganI wonder if #_:clj-kondo/ignore would work#2020-09-1820:08dharriganyes#2020-09-1820:08dharriganyes it does 🙂#2020-09-1820:08dharrigan
#_:clj-kondo/ignore
(comment
...
...
...
lots of redefining going on here...
...
...
,)
#2020-09-1820:11dharriganoh, not quite...#2020-09-1820:19dharriganactually sorry, wrong it does 🙂#2020-09-1820:19borkdude@dharrigan This seems to work for me:
(def x)
(def y)

#_:clj-kondo/ignore
(comment
  (def x)
  (def y)
  (def y)
  )
#2020-09-1820:20dharriganit works#2020-09-1820:20dharriganI was confused about something that it rightly pointed out, but was at the top of the file#2020-09-1820:20dharriganyes, it works grand 🙂#2020-09-1820:20borkdude@dharrigan More selectively:
(def x)
(def y)

#_{:clj-kondo/ignore[:redefined-var]}
(comment
  (def x)
  (def y)
  (def y)
  )
#2020-09-2418:58practicalli-johnExcellent, this will make my live coding broadcasts have fewer warnings, thank you 🙂 Its now an Emacs snippet#2020-09-2419:01borkdude:thumbsup:#2020-09-2419:54practicalli-johnAh, it works now I upgraded clj-kondo (I was a release behind, inconceivable) Thanks for this excellent project.#2020-09-2420:01borkdudethanks!#2020-09-1820:20dharriganyes, works totally 100% fine 🙂#2020-09-1820:20dharriganparty times! 🙂
#2020-09-1820:20borkdude🎉#2020-09-1820:21dharriganit found dead code 🙂#2020-09-1820:23borkdude"I can see dead code"#2020-09-1820:25dharriganI had a def and a defn of the same name#2020-09-1820:38dharriganOf course, I could have just used :skip-comments true in my configuration 🙂#2020-09-2010:21sogaiu@borkdude so i tried working on a hook for libpython-clj: https://gist.github.com/sogaiu/b6aa01efbd4006bbcab8decf2d5889aa in this case the construct is similar to a defn. is there something i can do to make the defined name show up in the analysis so i can use that toward indexing?#2020-09-2010:22borkdudeif you expand to a defn that uses that name, I think it should also show up in the analysis? if it doesn't, it might be a bug or there's some reason I don't know off the top of my head#2020-09-2010:23sogaiuthanks#2020-09-2010:25borkdudecould also be metadata related, forgetting to restore a position - not sure.#2020-09-2010:26sogaiuthanks for the tips#2020-09-2010:28sogaiuah i see rum's example tries to maintain metadata and i have not done so#2020-09-2011:23sogaiu@borkdude using with-meta made a difference in whether row, col info had something numeric. thanks!#2020-09-2014:03sogaiuthere was another piece to the puzzle. it turns out libpython-clj uses a construct similar to import-vars from potemkin (though it's not exactly the same), so i think if i write a hook for that, the indexing may work.#2020-09-2014:03sogaiuhttps://github.com/techascent/tech.parallel/blob/master/src/tech/parallel/utils.clj#L4-L27#2020-09-2014:16borkdude@sogaiu clj-kondo also has support for import-vars so if you rewrite to that, may also work #2020-09-2105:29sogaiu@borkdude thanks -- it's slightly different in form i think, but i adapted @lee's example to end up with this: https://gist.github.com/sogaiu/ad05cde3fd2529c11949903ca5993301 i transplanted the metadata so more info is available in the analysis: https://gist.github.com/sogaiu/ad05cde3fd2529c11949903ca5993301#file-utils-clj-L67-L72 @lee don't know if it's worth it for import-vars-with-mods, but it seems something similar could be done there.#2020-09-2105:32sogaiua downside of export-symbols and import-vars is that the indexed info points you at a location that doesn't make it convenient to get to the ultimate definition you'd likely be interested in seeing. contrast this with what core.async does: https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L56-L60 a tool might send you to those defns from usages but it's only one more step to use the tool again to get to the defintion that's being wrapped.#2020-09-2110:00borkdude@sogaiu I tend to go with the core.async approach and avoid tools like import-vars. I do support it in clj-kondo since it's pretty well established in the community#2020-09-2112:14lreadThanks @sogaiu, I will take a look. The import-vars approach most certainly has its pros and cons. Continueing with it in rewrite-cljc has taught me tons, which has been fun for me, but the amount of time I have spent on it has been, uh, lots. #2020-09-2112:21lread@borkdude, I do like sci’s copy-var, which is different but reminds me of import-var. https://github.com/borkdude/sci/blob/187c4551227c938090910b8ab3da024ca674c2ac/src/sci/core.cljc#L47#2020-09-2211:43hugodIs it possible to disable the arity-check for keywords? We have an embedded language that uses keywords in function position, with an arbitrary number of arguments.#2020-09-2211:57borkdude@hugod yes, let me get back to you after a meeting#2020-09-2212:04hugodNo urgency. Thanks for the config pointers. I see how to disable the check for a specific function/macro, but not for keywords in general. The set of keywords we use like this is open, although there is a limited set that probably covers most usage. Maybe that is good enough.#2020-09-2212:05borkdudeWriting a hook is probably the best solution, but requires some work#2020-09-2212:06borkdudeI assume these keywords are only used within a macro right?#2020-09-2212:36hugodWithin various macros, right. I’ll have a look at hooks. Thanks#2020-09-2213:46hugodUm, looks like it is not possible to define a hook on an unqualified symbol pulled in via a :refer :all#2020-09-2213:50borkdudeit depends if clj-kondo knows that namespace (e.g. it's been linted before)#2020-09-2213:50borkdudebtw, I think I have a hook here:#2020-09-2213:50borkdude#2020-09-2213:51borkdudeI assume the macro you use is required?#2020-09-2213:53borkdudeThis is the code:
(ns hooks.kw-macro
  (:require [clj-kondo.hooks-api :as api]))

(defn rewrite [node]
  (let [sexpr (api/sexpr node)]
    (if (and (seq? sexpr)
             (keyword? (first sexpr)))
      (let [children (rest (:children node))
            children (mapv rewrite children)]
        (with-meta (api/vector-node children)
          (meta node)))
      (with-meta
        (update node :children #(mapv rewrite %))
        (meta node)))))

(defn kw-macro [{:keys [:node]}]
  (let [new-node (api/vector-node (mapv rewrite (rest (:children node))))]
    ;; for debugging:
    ;;(prn :new-node new-node)
    {:node new-node}))
#2020-09-2213:54borkdudeI basically rewrite (my/kw-macro (:foo 1 2 3) (:bar 1 2 3)) to [[:foo 1 2 3] [:bar 1 2 3]]#2020-09-2213:59hugodThat should work with some modification to use walk to pick up nested forms. 🙂#2020-09-2213:59borkdudewalk unfortunately doesn't preserve metadata#2020-09-2214:00hugodI think I have a walk that does - thanks for the reminder#2020-09-2214:01hugodthe macro is required with a :refer :all and is actually defined in a different namespace via an import-vars like mechanism.#2020-09-2214:01hugodI can’t get the hook to trigger at all#2020-09-2214:01borkdudeyou're out of luck there, clj-kondo has no way of knowing what var you are calling#2020-09-2214:02borkdudeit does have support for import-vars (the widely used one). so if you use the same syntax as that one and use lint-as AND lint all of your namespaces, it might work#2020-09-2214:07hugodIs there any existing macro to inspect how clj-kondo is currently parsing an expression? eg, something I can insert around a form that prints the rewrite map#2020-09-2214:09borkdudeyes, look at the example I provided you#2020-09-2214:09borkdude
;;(prn :new-node new-node)
#2020-09-2215:11hugodduh, upgrading clj-kondo helps a lot#2020-09-2215:11borkdude:)#2020-09-2218:26hugodHow do you develop hooks? clj-kondo seems to just silently ignore the hook if it fails to load.#2020-09-2219:41borkdudeClj-kondo will print a warning if the hook isn’t found but is in your config #2020-09-2219:58borkdudee.g. with this config:
{:hooks {:analyze-call {my/kw-macro hooks.kw-macro/kw-macro2}}}
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "f89a978a939c8d9c9db8b5baa8cac8c9c1"}, :content ("[email protected]")}
^ @hugod
#2020-09-2219:59borkdudeand correcting it:
$ clj-kondo --lint example.clj
example.clj:5:14: error: clojure.core/inc is called with 3 args but expects 1
example.clj:6:28: error: clojure.core/inc is called with 3 args but expects 1
linting took 33ms, errors: 2, warnings: 0
#2020-09-2220:02hugodif there is a compile error in the hook itself, it seems to be silently ignored.#2020-09-2220:03borkdudelet me make a deliberate mistake#2020-09-2220:03borkdudeI'm putting a random x in my hook code:
$ clj-kondo --lint example.clj
WARNING: error while trying to read hook for my/kw-macro: Could not resolve symbol: x [at /private/tmp/proj/.clj-kondo/hooks/kw_macro.clj, line 5, column 3]
#2020-09-2220:05hugodum, I wonder what’s different here#2020-09-2220:06borkdudeyeah, you might have hit a different case. repro welcome, maybe something could be improved#2020-09-2220:08hugodhooks are very flexible :)#2020-09-2220:14borkdudepowered by the same interpreter as babashka#2020-09-2220:40borkdude@hugod could also be a laziness issue so the error is never reached?#2020-09-2220:41hugodGood thought. I’ll try and investigate more later.#2020-09-2211:57borkdudemeanwhile you might want to look at https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#2020-09-2211:58borkdudeI think this is what you're after: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exclude-arity-linting-inside-a-specific-macro-call#2020-09-2211:59borkdudealternatively you could write a hook for your macro, but that's more work than just suppressing warnings#2020-09-2407:25robert-stuttafordhi @borkdude 🙂 do you know if anyone has a reagent.core/with-let linter, that shows you unused bindings?#2020-09-2407:45borkdude@robert-stuttaford I think you can just use :lint-as + clojure.core/let for that#2020-09-2407:50robert-stuttafordok that simple, nice#2020-09-2407:51robert-stuttafordturns out we are...#2020-09-2407:54borkdudebut it doesn't work?#2020-09-2407:55robert-stuttafordno 😞#2020-09-2407:56robert-stuttafordit does correctly warn that symbols are not defined when used on the right side of the binding, but it doesn't warn that bindings in the form are unused#2020-09-2407:57robert-stuttaford#2020-09-2407:57borkdude@robert-stuttaford This warns that x is unused for me:
(ns foo
  {:clj-kondo/config '{:lint-as {reagent.core/with-let clojure.core/let}}}
  (:require [reagent.core :refer [with-let]]))

(with-let [x 1]
  (fn []))
#2020-09-2407:58robert-stuttafordok, i'll dig and see if i can figure out what's going on, thank you!#2020-09-2407:58borkdudemight be related to your config for defcomp#2020-09-2407:58borkdudewhich is probably a custom macro#2020-09-2407:58robert-stuttafordlol :unused-binding {:level :off} in config.edn is prrrrrrobably why#2020-09-2407:59robert-stuttafordthere's a comment citing this issue https://github.com/borkdude/clj-kondo/issues/885 which is now fixed yay#2020-09-2408:00robert-stuttafordok it works, false alarm, sorry for the noise#2020-09-2408:00borkdudenp :) btw, you use both Rum and Reagent?#2020-09-2408:01robert-stuttafordi'm helping a different team out with some stuff 🙂#2020-09-2517:43Kevineslint has a way to pass --fix which will auto fix errors that don't require programmer intervention. Is there a way to do this with clj-kondo?#2020-09-2517:56borkdudeno, clj-kondo won't touch your code#2020-09-2518:04borkdudethere are various tool that can, but they are mostly tied to editors, e.g. clj-refactor, clojure-lsp, etc#2020-09-2518:04borkdudethis is a tool that cut out unused vars: https://github.com/borkdude/carve#2020-09-2518:56Kevinhow would I configure linters when I'm using this library https://github.com/plumatic/plumbing . I want to use the :lint-as option instead of excluding it like this:
{:linters
  {:unresolved-symbol
    {:exclude [(plumbing.core/fnk)]}}}
#2020-09-2519:26borkdude@kevin26428 I think this works:
(ns foo
  {:clj-kondo/config '{:lint-as {plumbing.core/fnk clojure.core/fn}}}
  (:require [plumbing.core :refer (fnk sum)]))

(def stats-graph
  "A graph specifying the same computation as 'stats'"
  {:n  (fnk [xs]   (count xs))
   :m  (fnk [xs n] (/ (sum identity xs) n))
   :m2 (fnk [xs n] (/ (sum #(* % %) xs) n))
   :v  (fnk [m m2] (- m2 (* m m)))})
#2020-09-2519:51KevinThanks!#2020-09-2519:27borkdudeso {:lint-as {plumbing.core/fnk clojure.core/fn}}#2020-09-2520:01KevinI didn't see any mention of white space or indentation space checks in clj-kondo, is this configurable?#2020-09-2520:04borkdudeclj-kondo ignores all whitespace - I think there might be other tools concerned with formatting / indentation#2020-09-2520:06borkdudeI think it could do that, but personally I haven't really found this an issue worthwhile to work on, since formatting in the editors I use is pretty much automatic#2023-01-2517:59Matthew DowneyHey @U04V15CAJ - not to dig up ancient history but I wanted to check if the idea is still to keep indentation out of scope for clj-kondo. If so I'm thinking of using babashka + rewrite-clj to check for compliance with https://tonsky.me/blog/clojurefmt/ since it seems like an easy one to start with 🙂. My interest in this feature is mostly that while my editor does what I want it to, I want to be able to have a style guide for a project and not put myself in the position of bugging others to change little things in PRs or whatever (clj-kondo has been great for this already!).#2023-01-2519:06borkdudeDoes this relate with the comment in #CPABC1H61 about formatting and style/indent etc?#2023-01-2519:06borkdudesince lsp has formatting abilities and clj-kondo doesn't it might be good to join that conversation there#2023-01-2519:07Matthew DowneyOh no, total coincidence, hadn't seen it#2023-01-2519:08Matthew DowneyBut yeah makes perfect sense, will investigate doing this with cljfmt#2020-09-2520:19Noah Bogarti have a macro called wait-for that does a lot (too much probably). i have it listed in the :invalid-arity {:skip-args vector. because of this, i have an "unused binding" warning. if I remove the wait-for from the :skip-args vector, the "unused binding" warning goes away (as it should, because the binding is used inside the wait-for call)#2020-09-2520:21Noah Bogartany ideas why this might be happening?#2020-09-2520:40borkdude@nbtheduke Do you have a repro for me to look at?#2020-09-2521:16borkdude@nbtheduke E.g.:
(ns foo)

(defmacro wait-for [& _body])

(defn foo [x]
  (wait-for (inc x 1 2 3)))
$ clj-kondo --lint /tmp/foo.clj --config '{:linters {:invalid-arity {:skip-args [foo/wait-for]}}}'
linting took 11ms, errors: 0, warnings: 0
#2020-09-2521:16borkdudeI don't see x being unused#2020-09-2521:17Noah Bogarthttps://github.com/mtgred/netrunner/blob/master/src/clj/game/core/events.clj#L253#2020-09-2521:17Noah Bogartothers is referenced on line 265#2020-09-2521:19borkdudeCan you boil this down to a small repro?#2020-09-2521:19Noah Bogartlol I'll see what I can do. this repo is a mess#2020-09-2522:52Kevinhow do i exclude/handle things like tags #db/fn#2020-09-2607:01borkdude@kevin26428 can you elaborate?#2020-09-2610:33sogaiu@borkdude there is a construct in libpython-clj which appears to make certain namespaces / aliases available. it is called import-python. after it is evaluated, 7 namespaces / aliases become available. do you have a recommendation as to how to teach clj-kondo about this construct using hooks?#2020-09-2610:34sogaiufor starters i tried constructing a do form containing a require form, but i'm getting the sense that may not work.#2020-09-2610:38sogaiu#2020-09-2612:01borkdude@sogaiu Maybe:
(comment
  (require 'python.list))
(python.list/hi)
#2020-09-2612:10sogaiu@borkdude i see that that works in an editor, thanks. i tried with:
(comment
  (require (quote python.list)))
(python.list/hi)
but that doesn't seem to work in my editor. how do i construct a quoted form (i.e. using single quote) using the hooks api? i thought i might need to use rewrite-clj's quote-node but that doesn't appear to be in the hooks api. may be there is another way?
#2020-09-2612:13borkdudeHmm, clj-kondo's handling of require might not understand that currently. That's something to fix. But since you are writing a hook, this won't be emitted top level anyway?#2020-09-2612:13borkdudeclj-kondo only parses top-level requires currently#2020-09-2612:14sogaiuah i see.#2020-09-2612:14borkdudeor are you handling import-python at the top level?#2020-09-2612:14sogaiui think the typical place to use it is at top level, but doesn't the hooks api only let us return one node?#2020-09-2612:15borkdudethis is very co-incidental: I fixed a similar thing in sci recently: macros emitting top-level dos#2020-09-2612:15sogaiu🙂#2020-09-2612:15borkdudeI think there's two things to post issues for: - clj-kondo should handle requires in top-level dos - clj-kondo should handle require with quote#2020-09-2612:16sogaiuok, i'm fine to make those if you like.#2020-09-2612:16borkdudeyeah please. I'm about to start a new 2 week Clojurists Together cycle for clj-kondo :)#2020-09-2612:16sogaiucool, will do.#2020-09-2616:13borkdudeSophisticated CI script using babashka and clj-kondo in Gitlab: https://gist.github.com/hansbugge/4be701d771057e8ef6bbbb0912656355#2020-09-2812:12avocade@borkdude hey, what's the best way to disable all/most linting in (comment) blocks? 🙂 If that's possible…#2020-09-2812:13borkdude:skip-comments true#2020-09-2812:13borkdudehttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md#ignore-the-contents-of-comment-forms#2020-09-2812:13avocade🤓#2020-09-2812:14borkdudeAlso you can use #_{:clj-kondo/ignore [:redefine-var]} (comment ...) for more selectively ignoring things#2020-09-2812:24avocadeAlso getting a weird issue (we think): warning: unresolved namespace clojure.string. Are you missing a require? Getting this when we're just using a qualified fn directly like (clojure.string/upper-case "hi")… same with cognitect.rebl/submit and seemingly all other non-required forms 🙂#2020-09-2812:24avocadeObviously I'm missing something bigger hehe#2020-09-2812:26borkdudeyes, you need to require those namespaces. relying on other namespaces loading them for you is bad practice#2020-09-2812:26avocadeGot it, figured we were doing something non-best-practice :thumbsup:#2020-10-1410:48avocadeBtw, we're building something pretty cool on top of clojure/pathom/datomic called http://Fluent.to (https://fluent.to), would love to show it to you some time later next year and get your spontaneous input if you'd be interested. Seems pretty likely that we'll use sci heavily to run our internal "workflows" or "processes", whatever we end up calling them 🙂 PS. The website has been recently stripped down to not talk too much about what we're really building, so don't be fooled if it feels a bit uninspiring hehe#2020-10-1410:49avocadeAlso going on a European tour next year to meet up with interesting people (most clojure & rust devs and designers). so would love to pop by Amersfort on our way and say hi, and buy you a beer or two as thanks for your awesome work 😄 🍺#2020-10-1410:49avocadethe plan was originally to do it 6 months ago, but alas #corona#2020-10-1415:33borkdudeThanks! Would be cool :)#2020-10-1518:46avocadeCool, I'll start a new chat together with my Fluent-colleague @U06B8J0AJ to continue chatting over the months (so I won't have to be a go-between) 🙂#2020-09-2813:20avocadeI name a new (?) term HeisenLint for linter errors that appear in the background or in peripheral vision, and then mysteriously disappear when you look directly at them (cf HeisenBug). Just had one of those now, named it "Errorus Inssuficientinputus". There is an entire taxonomy of these things of course.#2020-09-2910:30ziltiFor those interested: I created an RPM for clj-kondo. AppImage and .deb builds may follow. https://build.opensuse.org/package/show/home:zilti:clojure/clj-kondo#2020-09-2910:32borkdude@zilti Amazing. Feel free to add to the install instructions in the clj-kondo repo#2020-09-2912:04seriogalooks like I cannot do #?(:clj #_{:clj-kondo/ignore [:unused-binding]}) 🙂#2020-09-2912:05borkdudethere's an issue for that, will fix#2020-09-2912:08borkdudeoh with reader conditional. can you please give the full example. it might be a different issue#2020-09-2912:34ullrichomg, I just spent an hour understanding why (name my-keyword) didn’t work while (clj->js my-keyword) did… classic case of shadowed variable. Can’t wait for kondo support for this 😄 “Name is forever nom.”#2020-09-2912:34serioga@borkdude full example is simple: I want to ignore bindings for :clj but not for :cljs. So I did not find solution for this. But I can create ticket.#2020-09-2913:02borkdude@serioga this works:
(ns foo-ns
  {:clj-kondo/config '{:linters {:unused-binding {:level #?(:clj :off :cljs :warning)}}}})

(defn foo [x]
  #?(:cljs x))
#2020-09-2913:03seriogabut I need to disable for the form only, not whole namespace.#2020-09-2913:12borkdudethen use an underscore for the branch you want to ignore#2020-09-2913:14serioga“then use an underscore for the branch you want to ignore” I did not understand, what do you mean
#_{:clj-kondo/ignore [:unused-binding]}
(defn- select-field
  [state column options idx remove-value classes]
  ...)
#2020-09-2913:16borkdude
(defn foo [#?(:cljs x
              :clj _x)]
  #?(:cljs x))
#2020-09-2913:16seriogathis is too hardcore 🙂#2020-09-2913:17borkdudeor simply:
(defn foo [x]
  x ;; ignore for clj
  #?(:cljs x))
#2020-09-2913:19borkdudewhat you would like is:
#_{:clj-kondo/ignore #?(:clj [:unused-binding] :cljs []}
right?
#2020-09-2913:19borkdudethis isn't supported yet, but I'll see what I can do for next release#2020-09-2913:20seriogawell, I aware about workarounds. I thought to use new “Ignore warnings in an expression” feature as less obtrusive but found that I want it to be selective for file type 🙂#2020-09-2913:21borkdudecan you confirm the above is what you want?#2020-09-2913:21seriogayes, I've tryed, it compiles and does not work :-)#2020-09-2913:22seriogayes, this is fine.#2020-09-2913:22borkdudeok, the problem is that reader comments are processed before reader conditionals, but I'll see if that can be fixed#2020-09-2913:24seriogaMaybe you will find place for the specification of the effective file type in the :clj-kondo/ignore data itself 🙂#2020-09-2913:25borkdudeI think using reader conditionals for this is more elegant#2020-09-2914:10seriogainteresting, clj-kondo does not parse valid (or)
Can't parse dev\user.clj, Wrong number of args (0) passed to: clj-kondo.impl.types.utils/union-type
#2020-09-2914:17borkdudefeel free to post an issue#2020-09-3018:06geraldodev@borkdude This week I've changed better-cond code to vanilla conds. clj-kondo is so deep integranted on my workflow that if it does not understand code it's not clojure 🙂#2020-09-3018:08borkdude@geraldodev hah. btw, I've got a hook for better-cond here: https://github.com/borkdude/clj-kondo/blob/master/corpus/.clj-kondo/hooks/better_cond.clj#2020-09-3018:09borkdudeit should really be moved here I guess: https://github.com/clj-kondo/config pr welcome ;)#2020-09-3018:09borkdudenot sure how complete it is#2020-10-0109:27dharriganOne of the things I'm playing around with is using this style of destructuring:#2020-10-0109:27dharrigan
(defn foo
  [{:keys [bar baz] :as config}]
  ...
  ...do something with bar
  ...do something with baz
  ...)
#2020-10-0109:29dharriganAs you notice, config is not being used, however, it is useful for documenting, as pointed out elsewhere ...two fns that look superficially similar can be immediately distinguished [by looking at the :as]#2020-10-0109:30dharriganCurrent clj-kondo flags config as not being used. I know I could put an unused var escape before the form or globally, but that's overkill (globally) or noise (individually for each form)#2020-10-0109:30dharriganCould clj-kondo have a configuration to ignore unused binding for :as?#2020-10-0109:31borkdude@dharrigan There is a recent issue for this.#2020-10-0109:31dharriganoooh#2020-10-0109:32dharrigan#2020-10-0109:32borkdudehttps://github.com/borkdude/clj-kondo/issues/1016#2020-10-0109:32borkduderight#2020-10-0109:32borkdudefor now the way to do this is to use :as _the-name#2020-10-0109:33borkdudeor :as #_:clj-kondo/ignore the-name but this needs fixing#2020-10-0109:33dharriganI'm sorta in agreement with the OP, using _ is a bit aesthetically out of place#2020-10-0109:33borkdudeyeah well, PR welcome. :)#2020-10-0109:33dharrigan🙂#2020-10-0109:33borkdudeif nobody will do a PR, I'll probably fix it relatively soon#2020-10-0109:33borkdudesince I'm getting paid for it by CT ;)#2020-10-0109:34dharriganw00t! 🙂#2020-10-0109:34dharriganI'll try to look (understand) the code base myself today to see if I can contribute#2020-10-0109:34borkdudeLet me mark this for the next release#2020-10-0109:34borkdudeOK#2020-10-0109:34dharriganbut um, don't wait for me 🙂#2020-10-0109:35borkdudeA hint: look in analyzer.clj in extract-bindings#2020-10-0109:35dharrigan👌#2020-10-0119:14KevinWhat would the lint-as equivalent be for this macro template/fn ?
; (template/fn args source)
; Example:
(def hello
  (template/fn [name] "Hello <%= name %>"))

(hello "Alice")
https://github.com/weavejester/comb I tried defn but defn has a function name before the args
#2020-10-0119:15borkdudeprobably clojure.core/fn#2020-10-0119:16borkdudebut you will get unused bindings with that, since kondo doesn't know about this macro#2020-10-0119:16borkdudeyou can suppress those with #_:clj-kondo/ignore[:unused-binding] before the (template/fn ...) call#2020-10-0119:46KevinIs it possible to do something like this:
{:linters {:unused-binding {:exclude [comb.template/fn]}}}
I tried this in my config.edn but it doesn't seem to be working
#2020-10-0120:03borkdudeAlas, that's not yet supported. Feel free to make an issue#2020-10-0119:18KevinI'm still new to clojure, but is it not possible to lint macros automatically without supporting them on a case by case basis#2020-10-0119:19borkdudeclj-kondo doesn't execute your code, so it can't know what your macro does, which is the fundamental problem#2020-10-0119:20borkdudethere are approaches that execute your code, but they aren't generally suited for editor integration because they are too slow#2020-10-0119:20borkdudealso these approaches tend to launch missiles#2020-10-0309:40borkdudeProposed config for shadowed-var linter: https://github.com/borkdude/clj-kondo/issues/646#issuecomment-703076742#2020-10-0514:40ghadikondo newb here: how hard would it be to make a linter that searched for over eagerness / redundant mapv's, e.g. (into coll (mapv ...)?#2020-10-0514:49borkdudewelcome ghadi! not sure, needs some thought#2020-10-0514:50borkdude@ghadi clj-kondo already has some type checking related stuff, so we can check for vector instead of seq as the second arg of into and do something with that#2020-10-0514:51borkdudee.g. now it has:
$ clj-kondo --lint - <<< '(into [] :foo)'
<stdin>:1:10: error: Expected: seqable collection, received: keyword.
#2020-10-0514:53ghadibasically I'm looking for ->> threads where there is a mapv not as the terminal operation#2020-10-0514:53borkdudeis this a one time analysis or something for general usage?#2020-10-0514:57ghadigeneral#2020-10-0514:57ghadiobviously it can't be perfect, but I think an analysis of the symbols would be Good Enough™, no need for static analysis#2020-10-0514:58borkdudeok, feel free to post an issue for this: https://github.com/borkdude/clj-kondo/issues there's also one potentially related issue: https://github.com/borkdude/clj-kondo/issues/323 someone wrote a hook as a solution for that: https://github.com/borkdude/clj-kondo/issues/323#issuecomment-691247062#2020-10-0514:59borkdudeso I expect that this can also be written as a hook maybe#2020-10-0514:59borkdudeas a first form of experimentation#2020-10-0515:01borkdude(hook docs: https://github.com/borkdude/clj-kondo/blob/master/doc/hooks.md)#2020-10-0515:32borkdude@ghadi
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "0c6e637e67687968694c414e5c3e3c3d35"}, :content ("[email protected]")}
#2020-10-0515:34ghadineat hook API#2020-10-0515:34ghadicool! that gives me a starting point#2020-10-0515:35ghadidoes clj-kondo support spec regexes?#2020-10-0515:37borkdudeinteresting point. that's a consideration for the future. I'm considering adding it to babashka and also to clj-kondo (both use sci for interpreting Clojure in the native binary). but there is the issue of alpha-ness: https://github.com/borkdude/babashka/issues/558#2020-10-0515:46borkdudeHold on#2020-10-0515:48borkdude@ghadi I made a hacked version of spartan.spec which runs with the current clj-kondo: https://gist.github.com/borkdude/85ad5edd88a1877ad2802a0d49ef6c3c so if you save that as spec.clj into .clj-kondo, then this works in the hook:
(s/def ::foo (s/cat :x int? :y string?))
(prn (s/conform ::foo [1 "foo"]))
$ clj-kondo --lint - <<< '(into [] (mapv inc [1 2 3]))'
{:x 1, :y "foo"}
<stdin>:1:10: warning: Avoid strictness in from
linting took 66ms, errors: 0, warnings: 1
Note that this is a hack but it might work for you
#2020-10-0515:48borkdudealso (require '[spec :as s])#2020-10-0515:49borkdudebut don't expect spec to be present in clj-kondo releases soon since it's not clear to wait for spec2, etc.#2020-10-0516:09ghadiwhat are the things in clojure.spec that sci can't handle?#2020-10-0516:10ghadi(assuming it's sci)#2020-10-0516:11borkdude@ghadi it is. at the time I wrote the spartan.spec port of spec, sci didn't support protocols yet, so I changed it all to just maps. but I'm pretty sure spec 1 and 2 can be made GraalVM compatible and hooked into the sci bindings of clj-kondo and babashka, so the spec functions themselves run at native speed instead of from interpreted code#2020-10-0516:14borkdudeif you now try to run clojure spec from source with bb, you'll get this:
$ bb -cp $(clojure -Spath) -e "(require '[clojure.spec.alpha])"
...
128:       (symbol (clojure.lang.Compiler/demunge f-ns) (clojure.lang.Compiler/demunge f-n)))))
                    ^--- Could not resolve symbol: clojure.lang.Compiler/demunge
This is because bb doesn't have the clojure.lang.Compiler class in its sci bindings
#2020-10-0516:15borkdudeand I'm pretty sure there's a few of these issues left when you work around that. The way forward for me would be to not run it from source but bind it natively. Spartan.spec is a stub meanwhile#2020-10-0616:55fiddlerwoaroofHas anyone used the clj-kondo analysis output to implement jump to definition in emacs?#2020-10-0616:55fiddlerwoaroof(and eldoc 🙂 )#2020-10-0617:08fiddlerwoaroofOk, I found jump-to-definition: https://github.com/sogaiu/alc.index-defs#2020-10-0617:37borkdude@fiddlerwoaroof also: https://github.com/didibus/anakondo#2020-10-0708:06didibusI have jump-to-definition on my to-do. That and eldoc are my next two, but I got kind of stuck with trying to make the analysis async so it doesn't freeze emacs first time you open a file from a project 😝 and that was a lot of work, so then I chocked and I put the whole thing on back burner haha. Thinking of getting back into it soon#2020-10-0806:31fiddlerwoaroofCould you piggieback on the data produced during the linting run @U0K064KQV? I figure the .clj-kondo cache directory ought to have all sorts of useful data that I just don’t have an interface into.#2020-10-0806:32fiddlerwoaroofThis project looks great, by the way. #2020-10-0903:06didibusYup, clj-kondo analysis data has everything I'd need. The row/col location of each var in each file and their name and doc is all there#2020-10-0903:07didibusAnd I maintain my own cache of it on a per-project basis in Emacs#2020-10-0918:41fiddlerwoaroofIs there a way to configure it to just re-use the cache I already have? It's not a huge deal, but it'd be a bit nicer to only actually compute that data once#2020-10-0918:43borkdudeanakondo uses its own cache. the format in .clj-kondo/.cache is an implementation detail which is not supposed to be used by other tools since it can change (it doesn't change often, but it could happen)#2020-10-0919:14fiddlerwoaroofThat makes sense, it'd be nice if there was a canonical database of analysis data that other tools could hook into.#2020-10-0919:16borkdudeI think it's better if tools keep their own caches, caching is hard enough as it is#2020-10-0919:17borkdudeBut it's likely that when you use anakondo to build up its cache, clj-kondo's cache will be populated as a side effect as well#2020-10-0923:20didibusI can also say that in practice, I've not seen any performance impact even on a 10 year old laptop that can't even run Google Chrome without crashing. The biggest issue for me right now is the initial time to analyse a project, and the fact that it blocks Emacs while doing that initial analysis. Most of the time there is taken by the Java analysis, not clj-kondo, so even then I don't think from clj-kondo's perspective its that big a problem for now.#2020-10-0923:21didibusAlso, syncing Emacs with a file based cache wouldn't be that simple, probably requiring its own cache for it 😛#2020-10-0923:22didibusWhat I have wondered though is more, if I decide to save my own cache to a file, so on Emacs restart you don't need to re-analyse the project, if I should re-use the clj-kondo's folder, or have my own folder, or store it within Emacs's own folder, etc.#2020-10-1007:00borkdudeYou can save it in .clj-kondo for sure #2020-10-1017:14fiddlerwoaroofI guess I was thinking more in terms of a database with an API that tools can be written against. I'd like to be able to query for code construvts with datalog or SQL, for example.#2020-10-1017:16fiddlerwoaroofAnyways, my grand vision for programming is more smalltalk-image shaped and less file shaped#2020-10-1018:14borkdudetotally possible to make a tool which puts clj-kondo's data into a SQL db: https://github.com/borkdude/babashka/blob/master/examples/hsqldb_unused_vars.clj#2020-10-1020:16didibusThe downsides of that is for an Emacs editing environment you now have to manage long lived subprocesses and that comes with its own issues.#2020-10-1020:17borkdude@U0K064KQV babashka + hsqldb is pretty fast, and not long lived, milliseconds#2020-10-1020:19borkdudeI haven't tested the feasibility of this, but you can try out the example in your own machine to see how it performs#2020-10-1020:22didibusHum... like if I didn't maintain a cache? It means clj-kondo would need to re-analyse all files every edit and re-initialize hsqldb and insert all vars and then run the query.#2020-10-1020:22didibusI don't know maybe clj-kondo and hsqldb are that fast#2020-10-1020:23borkdudethis is just an example of how to use hsqldb. I mean: you could maintain your own cache in a hsqldb#2020-10-1020:23borkdudeI'm not sure either#2020-10-1020:23didibusRight, that's what I meant by long lived process#2020-10-1020:23borkdudeno, it's persisted to disk?#2020-10-1020:23didibusIf I maintain my cache in a DB, that's a seperate process that Emacs as to start and manage#2020-10-1020:24didibusOh, is it?#2020-10-1020:24didibusSo you start hsql run some query over a a file based table and then kill it?#2020-10-1020:24borkdudeyeah. you can use it with babashka to create ad hoc databases on your file system, just like sqlite#2020-10-1020:25borkdudesqlite is also an option btw, if emacs has support for that somehow#2020-10-1020:25didibusOk, that's interesting then, I'll think about it. Could make my code easier, querying data-structures in Emacs is alright but that would make it much nicer#2020-10-1020:26borkdudeso, the support for hsqldb from within babashka comes from here: https://github.com/babashka/babashka-sql-pods/#2020-10-1020:27didibusThere's the downside of having users need to install one more binary, but I guess they are already expected to install clj-kondo#2020-10-1020:27borkdudeThat's for sure. Of course you could also make your own anakondo binary with GraalVM and use clj-kondo from there.#2020-10-1020:28borkdudeand include whatever database / EDN / EQL stuff you want#2020-10-1020:28borkdudePostgres and HSQLDB (embedded) are the only databases I've gotten to work with GraalVM#2020-10-1020:29didibusHum, ya that could be an option as well. I'll hammock on it all. Though at this point I wouldn't really see myself making a major refactor of that sort unless it really helped me down the road. But I like the ideas.#2020-10-1105:07fiddlerwoaroofMy ideal would be a standardized “database” of analysis information that could be populated by tools like clj-kondo and cider and used by various editor plugins as well as by ad-hoc user queries#2020-10-1105:07fiddlerwoaroofOf course, as someone who isn’t writing code (and doesn’t have time to) I'm grateful for the work y'all do#2020-10-1105:26sogaiuthere is also this project: https://github.com/jpmonettas/clindex#2020-10-0622:47sogaiu@fiddlerwoaroof this branch uses a much more recent clj-kondo fwiw: https://github.com/sogaiu/alc.index-defs/tree/update-clj-kondo#2020-10-0622:48fiddlerwoaroofThanks @sogaiu#2020-10-0712:30borkdudeSome progress on the new :shadowed-var linter:#2020-10-0712:31borkdudehttps://github.com/borkdude/clj-kondo/issues/646#issuecomment-704900810 https://github.com/borkdude/clj-kondo/tree/shadow-binding-646 feedback welcome, now it's still in the works.#2020-10-0713:55dominicmOmnomnom?#2020-10-0712:36dharriganthat's sooo nice!#2020-10-0713:01hugodIs there a pattern for suppressing unused warnings in defmulti dispatch function arguments?#2020-10-0714:02borkdude@hugod you can either start the args with underscores or use #_:clj-kondo/ignore or #_{:clj-kondo/ignore [:unused-binding]}#2020-10-0714:04hugodThanks. Might be nice to have a general option, since the dispatch fn arguments are seldom all used.#2020-10-0714:05borkdudeFeel free to post an issue about it and a proposal for the option#2020-10-0715:30borkdudeGot rid of all shadowed var warnings in clj-kondo 😅 https://github.com/borkdude/clj-kondo/commit/f8a43e1c5eb6e2ce840cb9656a3c43f788792b11#2020-10-0715:47borkdudeLol, I thought it didn't work in one spot, but I had a (:refer-clojure :exclude [ns-name]) in that namespace :)#2020-10-0715:47dharriganeating one's own dog food eh?#2020-10-0715:48borkdudeif clj-kondo's own code isn't compliant, the build fails - it's a good smoke test#2020-10-0719:19borkdudeI just pushed a snapshot release of clj-kondo (`2020.09.10-20201007.185225-22`) that fixes a memory problem when using clj-kondo in a long running process. Users that use clj-kondo in a long running process (on the JVM, as a library or LSP server) are advised to update to this version. Details: https://github.com/borkdude/clj-kondo/issues/1036 I already pushed out a new version of the clj-kondo VSCode extension with the fix. cc @snoe @robert-stuttaford#2020-10-0719:22borkdudeI will push a proper release later this week or next week, that will include some new features as well, but I didn't want to wait for this.#2020-10-0807:44eskosWhat would be the best way to tell clj-kondo to purge/refresh a project specific cache? I’m doing multi-library development for an internal project and our kondo caches seem to get out of sync quite easily for some reason when switching branches, probably at least partially due to how quickly our snapshot releases change.#2020-10-0807:44borkdude@suomi.esko You can rm -rf .clj-kondo/.cache#2020-10-0807:45eskosI don’t think I’m ready to live in the danger zone of putting rm -rf into git hook 😅#2020-10-0807:46borkdude@suomi.esko mv .clj-kondo/.cache .clj-kondo/.cache-old? ;)#2020-10-0807:47eskosThat’s better 🙂 But cool, throwing the entire thing out probably works the best in this case anyway 👍#2020-10-0809:20borkdudeMerged to master: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#shadowed-var Binaries can be obtained by navigating from Github to the CircleCI builds#2020-10-0814:21mbjarlandis there any way to bind clj-kondo to F2 in intellij/cursive so that you can iterate through the issues found by cursive and the issues found by clj-kondo?#2020-10-0814:22borkdude@mbjarland I think this depends on the plugin you're using for clj-kondo linting in IntelliJ. you might be able to find it in their docs#2020-10-0814:22mbjarlandfile watchers, but ok#2020-10-0814:23borkdudeSome people use FileWatcher, ah yes ok. So maybe there's something in the menu for FW#2020-10-0814:33mbjarlandok for posterity, in intellij you can go to Settings > Editor > Inspections and find File Watcher Problems and change the file watcher problem severity from "Weak Warning" to "Warning" and then the clj-kondo warnings will be included in the normal list of warnings reported (usually cycled through with F2 and visible in the top right file status widget)#2020-10-0814:35mbjarlandThe weak warnings are reported as well, but not cycle-able via F2
#2020-10-0815:14Karol WójcikIs there a hook which may support following macro?
(rfori [[index item] [1 2 3 4 5])]
   (println index item))
#2020-10-0815:18borkdudeI think you could just use {:lint-as {your.macro/rfori clojure.core/for}} for this, as clj-kondo doesn't care about your implementation as long as the syntax matches#2020-10-0815:21Karol WójcikWorks perfectly!#2020-10-0815:21Karol WójcikThank you @U04V15CAJ#2020-10-1009:54borkdudeClj-kondo v2020.10.10 New: shadowed var linter and various improvements and fixes Release notes: https://github.com/borkdude/clj-kondo/blob/master/CHANGELOG.md#v20201010 This release is funded by Clojurists Together.#2020-10-1011:40Luis SantosHi Maybe this is an existing feature but I cannot find information about it. Would it be possible to annotate a macro, using metadata, with lint-as rule so that I can have out-of-box linting support? And if not is there a technical limitation or would it be a bad practice to do this? Thanks for all great work.#2020-10-1011:45borkdude@luis559 Hi. This is not supported, since that would rely on clj-kondo linting the source of your macro in the right order, or at all and clj-kondo is not designed in such a way: it's designed to deal with incomplete information. A better way is to PR your config here: https://github.com/clj-kondo/config and then install the config using that lib.#2020-10-1011:46borkdudeI'm still considering something like picking up config from the classpath, but it's not yet clear#2020-10-1011:46borkdudeI think the config library could also be made to handle that#2020-10-1011:47borkdudeSo then users could provide a clj-kondo.config/your.org/your.lib/config.edn directory on the classpath#2020-10-1011:47borkdudeand this will then be copied, or something like that#2020-10-1011:49borkdudeThe issue for that is this one: https://github.com/clj-kondo/config/issues/1#2020-10-1011:51Luis SantosThe classpath option sounds promising as well. Thanks for explanation. Looking forward to see how it evolves. Thanks.#2020-10-1112:38pezA file like this causes an indexoutofbounds exception in the VS Code extension:
(def ^:foo)
#2020-10-1112:39pezI can't put the newline there it seems. It needs to be an empty line after the form to repro the error.#2020-10-1112:41pezI tried to repro it using the command line, but it didn't happen.#2020-10-1112:41pezThe output from the extension:
[Error - 2:40:39 PM] java.lang.IndexOutOfBoundsException
	at clojure.lang.PersistentVector.arrayFor(PersistentVector.java:158)
	at clojure.lang.PersistentVector.nth(PersistentVector.java:162)
	at clojure.lang.RT.nth(RT.java:896)
	at clj_kondo.lsp_server.impl.server$finding__GT_Diagnostic.invokeStatic(server.clj:75)
	at clj_kondo.lsp_server.impl.server$lint_BANG_$fn__11576.invoke(server.clj:132)
	at clojure.core$mapv$fn__8445.invoke(core.clj:6912)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:343)
	at clojure.core$reduce.invokeStatic(core.clj:6827)
	at clojure.core$mapv.invokeStatic(core.clj:6903)
	at clj_kondo.lsp_server.impl.server$lint_BANG_.invokeStatic(server.clj:124)
	at clj_kondo.lsp_server.impl.server.LSPTextDocumentService.didChange(server.clj:153)
	at jdk.internal.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$null$0(GenericEndpoint.java:65)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.notify(GenericEndpoint.java:152)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleNotification(RemoteEndpoint.java:220)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:187)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:194)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:94)
	at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:835)
#2020-10-1112:47borkdudeNice. Issue welcome here: https://github.com/borkdude/clj-kondo.lsp/issues Should be easy to fix probably#2020-10-1112:48borkdudeProbably happens here: https://github.com/borkdude/clj-kondo.lsp/blob/b72767efa23dda9f522edab9ec0f38f9afc61987/server/src/clj_kondo/lsp_server/impl/server.clj#L75#2020-10-1112:53pezIssue: https://github.com/borkdude/clj-kondo.lsp/issues/11#2020-10-1113:15borkdudeThanks#2020-10-1214:03viestiHmm, might have found an edge case in linter for format#2020-10-1214:05viestifrom the docs at https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html > Relative indexing is used when the format specifier contains a `'<'` ('\u003c') flag which causes the argument for the previous format specifier to be re-used.#2020-10-1214:06borkdudeNice! Feel free to post an issue. You can ignore this using #{_:clj-kondo/ignore [:format]}#2020-10-1220:10borkdude@viesti I now made the issue: https://github.com/borkdude/clj-kondo/issues/1042 I wonder why this feature is useful to anyone?#2020-10-1305:33viestiyeah, probably not useful, just happened to run into it and use in my code 😄#2020-10-1220:28Michael WWhat does clj-kondo mean here disambiguate?
(String. (b64/encode (.getBytes ^String "something")) "UTF-8")
Error:
Cannot disambiguate overloads of String
#2020-10-1220:29borkdude@michael819 That error isn't coming from clj-kondo, more likely from Clojure itself#2020-10-1220:30borkdudeMaybe b64/encode doesn't have a return type tag so you need to specify ^String probably (assuming it returns a string)#2020-10-1220:35Michael WIt was a byte-array thanks for the pointer on that.#2020-10-1417:57Stefan THey @borkdude I’ve got another repeatable issue I’ve noticed with the vscode extension, java.lang.IndexOutOfBoundsException is being thrown when you type something invalid, such as adding a comment in the middle of a list, example: step 1: add an empty list
()
step2: add a semicolon inside the list
(;)
results: an error is shown in the clj-kondo output
[Error - 10:56:50 AM] java.lang.IndexOutOfBoundsException
	at clojure.lang.PersistentVector.arrayFor(PersistentVector.java:158)
	at clojure.lang.PersistentVector.nth(PersistentVector.java:162)
	at clojure.lang.RT.nth(RT.java:896)
	at clj_kondo.lsp_server.impl.server$finding__GT_Diagnostic.invokeStatic(server.clj:75)
	at clj_kondo.lsp_server.impl.server$lint_BANG_$fn__11576.invoke(server.clj:132)
	at clojure.core$mapv$fn__8445.invoke(core.clj:6912)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:343)
	at clojure.core$reduce.invokeStatic(core.clj:6827)
	at clojure.core$mapv.invokeStatic(core.clj:6903)
	at clj_kondo.lsp_server.impl.server$lint_BANG_.invokeStatic(server.clj:124)
	at clj_kondo.lsp_server.impl.server.LSPTextDocumentService.didChange(server.clj:153)
	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$null$0(GenericEndpoint.java:65)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.notify(GenericEndpoint.java:152)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleNotification(RemoteEndpoint.java:220)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:187)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:194)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:94)
	at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
#2020-10-1418:02borkdude@stefan.toubia Thanks. This issue has been reported in the clj-kondo.lsp repo. The fix is pretty easy, PR welcome if you're up for it#2020-10-1418:05borkdudeThe exception happens on this line: https://github.com/borkdude/clj-kondo.lsp/blob/b72767efa23dda9f522edab9ec0f38f9afc61987/server/src/clj_kondo/lsp_server/impl/server.clj#L75#2020-10-1520:01dharriganWould it be interesting to flag up ;; TODO blah-dee-blah-blah type of comments?#2020-10-1520:02dharriganI put a few in my code, reminding myself to come back....I forget at times 🙂#2020-10-1520:04borkdudeI have been pondering about this for at least a few years ;) https://twitter.com/borkdude/status/1102604145348001797 https://twitter.com/borkdude/status/1273636271861227520 https://twitter.com/borkdude/status/872783644666068992#2020-10-1520:06dharrigan🙂#2020-10-1520:06dharriganI mean I could rg for them#2020-10-1520:07dharriganeasily enough, not an issue, just text after all#2020-10-1520:07dharriganbut but but....I like my clj-kondo 🙂#2020-10-1520:07borkdudeand what would you like clj-kondo to say about this: do or do not, there is no TODO?#2020-10-1520:07dharriganit's all a state of mind#2020-10-1520:08dharriganwell, it could be set to warn, or if you're feeling particularly sadistic, to error and thus throw off a build#2020-10-1604:36Ahmed HassanCan't we configure clj-kondo to flag some word or regex? this can flag TODO, FIXME kind of words.#2020-10-1606:39borkdudeBtw I remember that you once used babashka for a lot of requests with bb curl right? And this created too many processes on your machine #2020-10-1606:40borkdudeThere is now also org.httpkit.client built in which is also async #2020-10-1621:09Ahmed HassanYeah, that was missing piece of bb, I can't thank you enough for everything you're doing for community.#2020-10-1606:22Mikko HarjuHi! What would be the best way to lint a "let-like" macro that has the following signature:
(m/dynamic-let <var> <let-declarations> <body>)
#2020-10-1606:29Mikko HarjuI mean, I can just ignore the unresolved symbols altogether, but I'm interested if I could somehow piggyback on the let-declaration to get linting on the body based on the let-declarations.#2020-10-1606:29dharriganlint-as#2020-10-1606:30dharriganhttps://github.com/borkdude/clj-kondo/blob/master/doc/config.md#enable-optional-linters-1#2020-10-1606:31Mikko HarjuIt doesn't work directly as I have one parameter before the let declarations#2020-10-1606:34borkdude@U32ST9GR5 lint as Clojure.core/fn? #2020-10-1606:35Mikko Harju😮 of course!#2020-10-1606:36Mikko HarjuAh – a minor caveat...#2020-10-1606:36Mikko Harju
(m/let-dynamic dynamic-sub
  [data (if sub (re/subscribe sub) (atom nil))
#2020-10-1606:37Mikko Harjuthat does not work since fn cannot have dynamic declarations... Close but no cigar 🙂#2020-10-1606:38borkdudeAh. You can write a hook for it then, or suppress the unresolved symbols #2020-10-1606:38Mikko HarjuI'll dig into the hooks, thanks for the tip!#2020-10-1613:22Mikko Harju@U04V15CAJ fixed this with a hook, was very easy. Found a couple of typos in hooks docs, sent a PR to fix them. Thanks!#2020-10-1613:26borkdudenice :)#2020-10-1613:27borkdude
{:keys [:node]}
isn't a typo though, it's well supported
#2020-10-1614:58natehuh, TIL#2020-10-1616:55Mikko HarjuSame for me. TIL.#2020-10-1617:01Mikko HarjuFixed the PR to contain just the path change.#2020-10-1617:03borkdudeMerged, thanks#2020-10-1617:04Mikko HarjuNP!#2020-10-1613:38andrea.crottiis there anything around that uses clj-kondo to generate a static callgraph given a codebase?#2020-10-1613:38andrea.crottiand btw I noticed that both clj-kondo and clindex in their analysis return var, but don't know anything about functions for example#2020-10-1613:39andrea.crottiis that a limitation of the underlying analysis library I guess?#2020-10-1613:40borkdude@andrea.crotti https://github.com/benedekfazekas/morpheus#2020-10-1613:41borkdudenot sure what you mean with "don't know anything about functions" but the above library utilizes clj-kondo for making callgraphs, so yes, it's possible#2020-10-1613:46andrea.crottiI mean that you get var-definitions and var-usages, but I could not see how to say if a var referred to a function#2020-10-1613:47andrea.crottior something else, only macros were distinguished from what I could see#2020-10-1613:47borkdude@andrea.crotti How do you think carve does this?#2020-10-1614:10andrea.crottiyeah I looked at carve as well#2020-10-1614:11andrea.crottibut I can't really see that it distinguishes between variables and functions#2020-10-1614:11andrea.crottibut it probably just doesn't need to#2020-10-1614:26borkdudeah now I see what you mean#2020-10-1614:26borkdudeI think if there is no arity information, it's not a function - maybe#2020-10-1614:32andrea.crottiah ok yeah that already helps#2020-10-1913:14avocadeAny idea how to silence the linter errors for the naked (action [] …) and (remote [] …) definitions inside fulcro's defmutation macro? 🙂#2020-10-1913:15borkdude@avocade you can always put a #_:clj-kondo/ignore on it, if you can't solve it any other way. I'm not familiar with those macros#2020-10-1913:15borkdudeyou might want to write a hook for the defmutation macro though#2020-10-1913:16borkdude(https://github.com/borkdude/clj-kondo/blob/master/doc/hooks.md)#2020-10-1913:16borkdudeAlso see https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#2020-10-1915:12jaihindhreddyIs a PR welcome for https://github.com/borkdude/clj-kondo/issues/1042?#2020-10-1915:13borkdude@jaihindhreddy yes please - are you also using that in format?#2020-10-1915:13jaihindhreddyNope. The mere existence of false-positives bugs me for some reason 😅#2020-10-1915:14jaihindhreddyI did use relative indexing once for some online puzzle (before clj-kondo, a while ago)#2020-10-1915:14borkdudePR welcome :)#2020-10-1915:26jaihindhreddyhttps://github.com/borkdude/clj-kondo/pull/1045. (The checks ran successfully.)#2020-10-1915:37borkdude@jaihindhreddy I think we might as well just do (.charAt ^String s 1) instead of nth, since we know it's a string and don't need the polymorphic behavior which just wastes CPU cycles#2020-10-1915:38jaihindhreddyYeah, considered it, and thought it might be a premature optimisation. In retrospect, the string is created within the function, and I'm just wasting CPU with nth. Changing.#2020-10-1915:40jaihindhreddydone#2020-10-1915:41borkdudeThanks!#2020-10-1915:44jaihindhreddyhttps://github.com/borkdude/clj-kondo/issues/378 seems like a false flag. Perhaps it can be closed.#2020-10-1915:46borkduderesponded in issue#2020-10-2214:19martinklepschIs there a way to ignore issues from (comment) blocks?#2020-10-2214:25borkdude@martinklepsch Jasicher!
#_{:clj-kondo/ignore [:whatever-linter :whatever-linter2]}
(comment ...)
#2020-10-2214:25borkdudeor just #_:clj-kondo/ignore to ignore all#2020-10-2215:22martinklepschawesome, that is perfect. Thank you very much 🙂#2020-10-2215:25borkdudeYou can also do this: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#ignore-the-contents-of-comment-forms#2020-10-2216:13lreadWe actually currently do this for cljdoc, https://github.com/cljdoc/cljdoc/blob/fb6af911adc9209b986f2776f39394983b97a171/.clj-kondo/config.edn#L2.#2020-10-2306:05Mikko HarjuGood morning 🙂 I hit an issue with multi-arity macros with CLJS, it says that it has the wrong arity, although the code compiles and works as expected. Should this be an easy problem to fix? If so – maybe I could help out with it. EDIT: nevermind, was the cache. Clearing it fixed the issue.#2020-10-2716:51andrea.crottiif I have something declared with a macro like (defmymacro x 1) and then it's below in the same namespace, I can ignore easily the defmymacrolines, but how do I ignore the usages of these vars?#2020-10-2716:53borkdude@andrea.crotti I think you can use {:lint-as {your-awesome-lib.defmymacro clojure.core/def} for this#2020-10-2716:54andrea.crottiah nice didn't think about that#2020-10-2716:57andrea.crottiand also should Emacs with fly-clj-kondo read the .clj-kondo/config.edn file right?#2020-10-2716:57andrea.crottiit looks sometimes that running from the cli and what I see in Emacs are out of sync#2020-10-2718:02borkdudeshould not be the case, the same binary is invoked. you might want to restart emacs and see if that solved anything#2020-10-2717:31hugodIs it possible to write tests for hooks? I don’t see how to define a project that makes clj-kondo.hooks-api available.#2020-10-2718:01borkdude@hugod I usually test this by just writing examples and see if they work: https://github.com/clj-kondo/config/blob/master/resources/claypoole/src/example.clj you could also just run clj-kondo (binary or JVM), capture the output (as strings or EDN) and then write tests on that (using the JVM or babashka)#2020-10-2718:07hugodI was hoping to run it in a project so I could also debug the hooks. clj-kondo seems to be silently ignoring my config and I’ve no idea why. I’m not sure if the config is somehow wrong, or there is an error in my hook, or…#2020-10-2718:07borkdudeclj-kondo prints a warning if it can't find the hook#2020-10-2718:08borkdudeyou can stick a prn/println in the hook to force some output#2020-10-2718:08borkdudeif the hook doesn't return a map with :node then it continues to lint without a transformed node, but with the original node#2020-10-2718:09hugodI don’t get output from either of those#2020-10-2718:09borkdudethis is by design, since hooks don't always transform nodes#2020-10-2718:09borkdudethen maybe your config is off.#2020-10-2718:10borkdudepost a small repro repo and I'll take a look#2020-10-2718:10borkdudeyou can also post your config.edn, so I can see if there's something wrong#2020-10-2718:11borkdudecould also be that you're using an old version of clj-kondo. many things can be wrong without clj-kondo being able to print an error#2020-10-2718:16hugodthanks for the offer - not sure I can post it as is. Using v2020.10.10. The config is valid edn at least 😉.#2020-10-2718:17borkdudemaybe post the hook config only if you're able to#2020-10-2718:20borkdudethere could very well be a typo somewhere#2020-10-2720:30hugodlooks like clj-kondo sometimes manages to resolve the symbols that are being hooked and sometimes it doesn’t. I’m trying to find a pattern to this. It seems to work when linting the whole class path. The symbols are used unqualified in code through a :use, which I guess is the root of the problem. Can’t change the code base in that respect though.#2020-10-2720:46borkdudeAh right!#2020-10-2720:47borkdudeThere is an issue about this: https://github.com/borkdude/clj-kondo/issues/1010 clj-kondo tries to do its best to resolve those vars, but this is at the very end of the linting, where the cache is consulted.#2020-10-2720:48borkdudeas clj-kondo doesn't recommend refer :all or :use I have marked this issue as low priority#2020-10-2720:48borkdudebut if there's enough relevant problems associated, I might give it more priority#2020-10-2720:57hugodIn our case we have a language embedded in clojure, so we have great chunks of code that import the language with :use.#2020-10-2720:58borkdude@hugod Clj-kondo should work fine if you have only one :use at a time#2020-10-2720:58borkdudeProvided you have linted that other namespace as well. Else clj-kondo has no way of knowing what vars that other ns has#2020-10-2720:59hugodunfortunately, we usually have several. Definitely better behaviour once the cache is built.#2020-10-2721:00borkdudeok, then 1010 needs to be solved to support this#2020-10-2721:00borkdudemaybe you could make a small comment there explaining your use case#2020-10-2718:56jfntn👋 I’ve seen some mentions of orchestra.core/defn-spec in the github issues and I’ve tried adding {:lint-as {orchestra.core/defn-spec clj-kondo.lint-as/def-catch-call}} to my config.edn but I’m still getting unresolved-symbol errors for all the fn args. Is there a solution to this?#2020-10-2720:50borkdudeCan you give an example? Clj-kondo now supports hooks so this might be the better way to support that macro#2020-10-2720:50borkdudeSee https://github.com/borkdude/clj-kondo/blob/master/doc/hooks.md#2020-10-2722:09jfntnNice work on that api, def looks doable!#2020-10-2722:09jfntnUsage looks something like this:
(defn-spec arities number?
  ([a number?]
   (inc a))
  ([a number?, b number?]
   (+ a b))
  ([a string?, b boolean?, c map?]
   0))
Where the predicates are specs
#2020-10-2722:10borkdudethat looks quite doable then yes. there are other examples here: https://github.com/clj-kondo/config#2020-10-2722:10borkdudeyou can PR your config there if you want, so others can profit#2020-10-2722:10borkdudeI also want to support picking up configs/hooks from library dependencies themselves in that config project#2020-10-2916:24Stefan@borkdude Should the clj-kondo vscode plugin also pickup .clj-kondo/config.edn automatically? If not, can I configure clj-kondo in vscode somehow?#2020-10-2916:24borkdudeyes, no#2020-10-2916:25StefanHmm that doesn’t seem to work for me. When I run clj-kondo on the command line, I don’t get the lint error anymore that I’m trying to solve, but when I look in vscode (plugin installed through calva) then I do see the lint error. Any tips?#2020-10-2916:26borkdudecan you make a minimal repro and post the versions of both clj-kondo's?#2020-10-2916:27StefanSure, I’ll let you know when I have it. Thanks!#2020-10-2917:09Stefan@borkdude Here it is: https://github.com/svdo/clj-kondo-issue. I tried to explain in the README what I’m looking at. Please let me know if anything is unclear.#2020-10-2917:13borkdude@stefan.van.den.oord Works fine over here. Are you opening the directory like I have opened it, or are you editing files outside your "workspace" ?#2020-10-2917:33StefanI’m launching vscode by typing code .in the project folder.#2020-10-2918:19borkdudeI'll also try that#2020-10-2918:19borkdude@stefan.van.den.oord Same, works fine over here#2020-10-2918:23StefanHmm strange. Is there a cache being used outside the project folder? Did you also try with calva enabled/disabled? Come to think of it, maybe I have the joker extension enabled as well, might also come from there. I’ll try disabling it (AFK ATM)#2020-10-2918:25borkdude@stefan.van.den.oord That error looks like it comes from joker yes:
$ echo 'conn' | /usr/local/bin/joker --lint -
<stdin>:1:1: Parse error: Unable to resolve symbol: conn
$ echo 'conn' | clj-kondo --lint -
<stdin>:1:1: error: unresolved symbol conn
#2020-10-2919:03StefanIndeed, that was the issue. Thanks for helping me to pin this down!#2020-10-3010:26Jim NewtonHi everyone, just started using kondo. question. what should I do to make it not complain about my macros? Or better, to make it check macros correctly?#2020-10-3010:27borkdude@jimka.issy There are several options for this: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#unrecognized-macros#2020-10-3010:31Jim Newtonhmmm. are those workarounds really satisfying to kondo users?#2020-10-3010:31Jim NewtonI use lots of macros in my code, it would be great if kondo would check the expanded code.#2020-10-3010:31Jim Newtonand even report that macroexpand fails.#2020-10-3010:32borkdude@jimka.issy This is a general problem in Clojure and static analysis tooling. The trade off is either execute macros at the penalty of performance and launching missiles or mechanisms like this to assist static analysis which make it feasible for near realtime feedback#2020-10-3010:33borkdudeThe closest thing for making clj-kondo aware of your custom macros and getting good custom checks is writing hooks for it. The other options are linting as existing macros or suppressing warnings.#2020-10-3010:33Jim Newtonyes, that is a real trade off. I realize that some macros (even some of my own) are really cpu intensive. But I'd love the option, as most macros are NOT cpu intensive, but simple code transformations.#2020-10-3010:35borkdudeWhen writing the hooks API I have considered that. But it isn't possible since keywords, numbers, strings etc, do not carry metadata, so you will lose location information. It's not likely that clj-kondo will support executing user macros as is anytime soon.#2020-10-3010:36Jim Newtonis clj-kondo executing in a different process? or is it executing in the same nrepl process as emacs/cider is using?#2020-10-3010:36borkdudeClj-kondo is its own environment, not attached to the JVM at all (if you're running the binary)#2020-10-3010:37Jim Newtonit's not using the JVM? that sounds like a huge amount of work.#2020-10-3010:37borkdudeYou can lint arbitrary .clj and .cljs files on a system without any other Clojure tools on it#2020-10-3010:37borkdude@jimka.issy If you like to use a JVM-attached linter that will expand your macros take a look at eastwood#2020-10-3010:37Jim Newtondo my comments echo every first-time user's comments? sorry if they do.#2020-10-3010:38borkdudeIt's a common question, but in most projects I've worked on, the macro config only contains a hand full of things#2020-10-3010:38Jim Newtoni see.#2020-10-3010:39borkdudeIn Clojure writing lots of macros isn't really encouraged anyway. Clj-kondo supports most well known macros, at least from Clojure itself and several popular libraries#2020-10-3010:39Jim NewtonIt seems I looked at eastwood sometime ago and abandoned it. Perhaps because it easily gets confused with namespaces.#2020-10-3010:39borkdudeAnd hooks offer enough flexibility to support the wildest custom macros now#2020-10-3010:40borkdudeHere is a repo with hooks for some libraries: https://github.com/clj-kondo/config#2020-10-3010:40Jim Newtonnot your fault of course, but it is unfortunate that such a powerful feature of the language is discouraged.#2020-10-3010:41borkdudeEver heard of the first rule of macro club? :) https://stuartsierra.com/download/2010-10-23-clojure-conj-macro-club.pdf#2020-10-3010:42borkdudeI mean, I do use them, and it's annoying that clj-kondo doesn't recognize the syntax out of the box, but it's not something I can easily fix while also keeping clj-kondo fast and accurate#2020-10-3010:50Jim Newtonkondo does find lots of problems with my code. notably misplaced docstrings.#2020-10-3010:51Jim NewtonI very often use the Common Lisp definition order.#2020-10-3010:54borkdude@jimka.issy The initial inspiration for clj-kondo was joker: it's a linter that I could easily hook up with emacs and it worked without a running REPL. I extended the way it works with more features and this became clj-kondo. You can watch the talk in the README (ca. 20 minutes long) if you want to know more about how clj-kondo works and the trade-offs it makes.#2020-10-3010:59Jim Newtonhow does condo figure out whether a symbol is resolvable. It seems to get this wrong in lots of cases for me.#2020-10-3011:00borkdudeIt depends. If you have a concrete example, I can tell you why.#2020-10-3011:01Jim NewtonI suspect it is related to (in-ns ...) does clj-kondo know that top-level regions between two calls to (in-ns ...) should be interpreted in the name space specified?#2020-10-3011:02borkdudeIt knows. But if clj-kondo hasn't linted the other ns yet, it might not know which symbols are in it. To make clj-kondo aware of this, you should do this: https://github.com/borkdude/clj-kondo/#project-setup#2020-10-3011:03Jim Newtonyes I did that before I started. do I need to redo it from time to time?#2020-10-3011:04borkdudein that case, it might be a bug. Not sure. If you can make a repro as in: I've linted this file and I'm using in-ns of the ns of that file in this other file, but it doesn't work, I will take a look.#2020-10-3011:04Jim NewtonBTW when I parallel lint, it printed out volumes of diagnostics from libraries I'm referencing#2020-10-3011:04borkdudeyeah, you can ignore that with > /dev/null if you want#2020-10-3011:06borkdudemaybe the README should mention that#2020-10-3011:11Jim NewtonI'm happy to send you the issue by email, or chat, or and also happy to file it in the issue tracker on github as you prefer.#2020-10-3011:13borkdudeGithub issue would be good#2020-10-3011:16Jim NewtonBy "Which platform are you using?" You mean Mac/Linux/windows?#2020-10-3011:17borkdudeyeah#2020-10-3011:28Jim NewtonOK, I filed a issue #1054 https://github.com/borkdude/clj-kondo/issues/1054 Thanks for the offer to take a look.#2020-10-3011:37borkdudeThanks. I hope to take a look soon. I think the in-ns logic might not remember the requires from the original ns well enough, something along those lines.#2020-10-3011:38borkdudemeanwhile, as a workaround you can use namespace local config to suppress those symbols#2020-10-3022:58borkdudeUsers of clj-kondo may also like: https://github.com/borkdude/grasp I just added an example of how to find all occurrences of keywords in e.g. a re-frame app: https://github.com/borkdude/grasp#finding-keywords Discuss in #grasp for more.#2020-10-3115:34dominicmI'm considering automatically running clj-kondo --parallel --lint in the background on JVM startup. Any reason not to?#2020-10-3115:37borkdudebattery life?#2020-10-3115:39dominicm@borkdude seems like a non-issue, given that it's only on the rare reboot of the JVM. Does clj-kondo cache at all for that operation?#2020-10-3115:40borkdudeclj-kondo always caches when there's a .clj-kondo dir, unless --cache is false#2020-10-3115:41dominicm@borkdude so the files in jars won't be re-linted?#2020-10-3115:42borkdudeoh you mean like if you call --parallel --lint next time, it will skip the jars? no it doesn't have logic for that#2020-10-3115:42borkdudethere's an issue for this. let me look it up#2020-10-3115:42dominicmAh. I'll start with naïve approach, and assume clj-kondo will either fix it later, or I can just cache against the .cpcache :)#2020-10-3115:42borkdudehttps://github.com/borkdude/clj-kondo/issues/705#2020-10-3115:43borkdudethere's a bb script in there ;)#2020-10-3115:44borkdudeIt's possible to build this logic inside clj-kondo, but then we've got a cache for the cache, which may introduce ... issues?#2020-10-3115:44dominicmheh, that appears to be from a project I worked on :p.#2020-10-3115:44borkdudeyou worked with daniel compton?#2020-10-3115:45dominicmHmm, that depends I guess? :) I wouldn't describe this as a cache, the existing thing is more of a "lint history" or "lint record"#2020-10-3115:45dominicmSo a cache would be a literal cache for that lint history#2020-10-3115:46borkdudeyes, cache is maybe the wrong word, but I also didn't want to call it a database#2020-10-3115:47dominicmHypothetically, clj-kondo could be taught how to resolve namespaces by itself and then it could check the "database" OR just resolve it as a fallback. Hypothetically ofc, there's a bunch of thinking that would need to go into that.#2020-10-3115:47borkdudeI think using the cpcache for this might be a nice idea btw, post it in the issue :)#2020-10-3115:48dominicmAm I safe-ish to create files in .clj-kondo/cache? If so, I'll use the cpcache as my approach.#2020-10-3115:48borkdudeyeah, you can put anything in the .cache dir, clj-kondo won't punish you#2020-10-3115:49borkdudeyou could even have a global cache I guess of linted jars#2020-10-3115:49borkdudelike ~/.clj-kondo/.cache/foo.jar/....#2020-10-3115:50borkdudeand when clj-kondo lints the jar it will just copy it from there or something#2020-10-3115:50dominicmI might encourage a symlink if possible. Learning from the npm->yarn transition!#2020-10-3115:50borkdudeyeah, or clj-kondo will just do lookups to a global cache as a fallback#2020-10-3115:51borkdudemeh#2020-10-3115:51borkdudeI can already feel the github issues coming ;)#2020-10-3115:51borkdudebut it could be nice. lint your .m2 dir once, profit many times#2020-10-3115:51dominicmfwiw, I think clj is going to pursue a similar idea for AOT.#2020-10-3115:52dominicmhttps://clojure.org/guides/dev_startup_time automating this process#2020-10-3115:52dominicmor maybe for prod, not sure. Alex hinted at it.#2020-10-3115:52dominicmImmutable deps make this a lot easier#2020-10-3115:52borkdudeyeah#2020-10-3115:54borkdudethe cache is also keyed on .clj-kondo version btw, so updates to clj-kondo would invalidate it#2020-10-3115:54dominicmMakes sense.#2020-10-3115:54dominicmBtw, if any other tricks like this come to mind that a project could experiment with, let me know. I'm working on a place for hacks like this to be tested in a way that wouldn't require long-term commitments on your part.#2020-10-3115:57borkdudeother tricks can be posted in the issue I guess?#2020-10-3116:00dominicmI meant unrelated to caching :) Others similar to auto-caching on JVM startup#2020-10-3116:01borkdudeah right.#2020-10-3116:09dominicm
❯ time clj-kondo --parallel --lint  /home/overfl0w/.m2/repository/refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0.jar
<snip>
clj-kondo --parallel --lint   4.77s user 0.35s system 99% cpu 5.163 total
❯ time clj-kondo --parallel --lint  /home/overfl0w/.m2/repository/cider/cider-nrepl/0.25.3/cider-nrepl-0.25.3.jar
clj-kondo --parallel --lint   7.82s user 0.38s system 99% cpu 8.272 total
That's... impressively slow :p
#2020-10-3116:11dominicmI suspect that's mostly my machine being old, but also the size of these two jars is probably disproportionate. They contain embedded tools reader copies, etc.#2020-10-3116:11dominicmMight be worth doing a content cache I guess, not sure if you do already#2020-10-3116:11borkdudeyou mean, like hashing the source?#2020-10-3116:12borkdudeclj-kondo doesn't use any of this, it just re-lints every time you feed it something#2020-10-3116:18borkdude@dominicm btw, the JVM may be a tad faster due to JIT#2020-10-3116:18borkdudeso you could also include clj-kondo as a JVM dep#2020-10-3117:00dominicmHmm, don't think that's useful necessarily here. As if the user doesn't have clj-kondo installed, then the cache isn't much use to them.#2020-10-3117:00dominicmWill ponder.#2020-10-3117:05borkdudeok#2020-11-0110:20borkdudeIf you want to contribute to any of my projects: I'm keeping a list of 'PR welcome' issues here: https://gist.github.com/borkdude/18af5d96c6465ce64144f03636fda3dc#2020-11-0216:38hugodIn a hook, is it possible to set :clj-kondo/ignore on the rewritten forms? e.g. if we rewrite something as a let we don’t want clj-kondo to complain about a redundant let in the body.#2020-11-0216:38borkdude@hugod In the newest clj-kondo, clj-kondo should already not complain about this anymore. Which version are you using?#2020-11-0216:39borkdudeThe latest version is 2020.10.10#2020-11-0216:46hugodUsing the version you patched to early load the cache#2020-11-0216:49borkdude@hugod The current behavior should be: if any of the two nested let nodes doesn't have location metadata, there is no warning.#2020-11-0216:52hugodThe replacement node (the let) that is being generated has the input node’s meta set on it - is that not the intended pattern?#2020-11-0216:52borkdudeif that's the outer node returned, then that's probably good. but you are generating another let inside of that?#2020-11-0216:52borkdudeoh I see#2020-11-0216:53borkdudeif the user then uses your node inside their let, it will warn. in this case, it's maybe better to leave out the location metadata#2020-11-0216:54borkdudeyou can put an ignore on that probably, but this will disable linting for all the inside nodes as well#2020-11-0216:54hugodAlmotst - the generated let contains the body of the macro expression, which happens to be a let#2020-11-0216:55borkdudeyeah, same problem#2020-11-0216:55borkdudewhen generating a let, it's probably better to not attach location metadata, as to not trigger the redundant let linter#2020-11-0216:55hugodok, got it, thanks#2020-11-0216:57hugodWhat does omitting the metadata do to reported line numbers if the let binding contains a lint error/warning?#2020-11-0216:59borkdudethe let itself probably doesn't have warnings, if it's generated syntactically correct. when you will have unused bindings, the location of the binding symbols is used instead#2020-11-0216:59borkdudeto avoid those warnings you could use underscored symbols#2020-11-0217:00borkdude@hugod another approach is to use let* which also will never trigger a warning, but this is kind of undocumented behavior. I was hoping the location metadata rule was sufficient#2020-11-0217:00borkdudeif that turns out not to be the case, we could make this explicit using some bespoke metadata#2020-11-0217:01borkdudeor we could always add metadata on the generated nodes, so clj-kondo has a different way to know that the node was generated using the API#2020-11-0217:03borkdudemaybe that's more robust#2020-11-0217:07hugodNot adding metadata should work for now, but it might be nice not to have to think about this as a hook writer.#2020-11-0217:07borkdude@hugod The check to suppress a warning is this: https://github.com/borkdude/clj-kondo/blob/b8a9bac8748999b0ea96db70c2a3cb4d1d3c27fd/src/clj_kondo/impl/analyzer.clj#L574 We could make that (:clj-kondo.impl/generated (meta node))#2020-11-0217:08borkdudeand then automatically add that to all the generated nodes#2020-11-0217:09borkdudeok, I'll change this to make that more robust#2020-11-0217:11borkdudehttps://github.com/borkdude/clj-kondo/issues/1059#2020-11-0219:38borkdude@hugod I now pushed this change, so you can re-add your location metadata and you should not get a warning with latest master#2020-11-0221:46hugodThank you, again!#2020-11-0310:54Adrian SmithIs it worth down playing the documentation for file watchers in intellji? It's such a hacky experience in comparison to the LSP approach - I can't think of any reason why you would want to use the file watchers over LSP, but the docs look more imposing for beginners with it in#2020-11-0310:58borkdudeI don't use IntelliJ myself so whatever the community thinks is good, I'll take it#2020-11-0311:04borkdude@sfyire so feel free to PR a doc change#2020-11-0315:18raymcdermottI'm getting a warning > unresolved symbol the-ns #2020-11-0315:19raymcdermottbut why though?#2020-11-0315:19raymcdermotthttps://github.com/clojure/clojure/blob/38bafca9e76cd6625d8dce5fb6d16b87845c8b9d/src/clj/clojure/core.clj#L4153#2020-11-0315:23borkdudeWithout more context, I can't reproduce the problem.#2020-11-0315:24borkdudeMy guess is that you're in .cljc and you're not using the code in a :clj branch#2020-11-0315:41raymcdermottha! yes#2020-11-0315:42raymcdermottso that is not in CLJS?#2020-11-0315:42borkdudenope#2020-11-0315:44raymcdermottgoddam ... TIL#2020-11-0315:46practicalli-johnclj-kondo tells me off if I use :some-other-keyword rather than :else as the last thing in a cond expression. Can I add a config to say just detect a keyword, rather than a specific :else keyword. Or should I just follow the clojure style guide and not be quirky 🙂#2020-11-0321:41dominicmWhat a strange choice instead of :else... 😉#2020-11-0315:47borkdude@jr0cket That rule comes straight from the community clojure style guide, and you can turn that rule off#2020-11-0315:48borkdude@jr0cket https://github.com/borkdude/clj-kondo/blob/5a4e3a139012586ddb788910010cdb1fa97383b5/src/clj_kondo/impl/config.clj#L21#2020-11-0410:04Charlie Briggshey, I was wondering how I’d setup clj-kondo to not report unresolved-symbol for things extending clojure.test, e.g. thrown-with-data? here: https://clojureverse.org/t/testing-thrown-ex-info-exceptions/6146/3?#2020-11-0410:05borkdude@charliebriggs https://github.com/borkdude/sci/blob/971614de14a6fd00e6991d1afd6c0ce9fbda104c/.clj-kondo/config.edn#L3#2020-11-0410:05Charlie Briggswonderful, thank you very much#2020-11-0411:55paulbutcherI’m just getting started with clj-kondo, so please forgive me if I’m missing something obvious. In my test code, I tend to use :refer :all to drag in the namespace that I’m testing, which clj-kondo unsurprisingly warns about. I’ve worked out that I can disable this warning by putting {:linters {:refer-all {:exclude [my.namespace.here]}}} into my config.edn but that disables the warning everywhere. I only want to disable it within test code. Is there any way that I can achieve that?
#2020-11-0515:17practicalli-johnIf you are able to change the code, then use :refer [deftest is testing] instead of :refer :all which is more common approach to requiring vars.#2020-11-0412:03borkdude@paulbutcher you can use namespace local config to achieve that#2020-11-0412:03borkdudeor an ignore hint#2020-11-0412:03paulbutcherAn ignore hint is inside the source code, yes? How do I create namespace local config?#2020-11-0412:05paulbutcherOh! Is it just a .clj-kondo directory inside the namespace?#2020-11-0412:06borkdude
(ns foo (:require #_:clj-kondo/ignore [foo.bar :refer :all]))
;; or
(ns foo {:clj-kondo/config {:linters {:refer-all {:level :off}}}}
    (:require [foo.bar :refer :all]))
#2020-11-0412:06borkdudeso both in source#2020-11-0412:07paulbutcherAh! Got you.#2020-11-0412:08paulbutcherThanks!#2020-11-0419:56benny@borkdude sorry to get back to the graal thingie, but clj-kondo can't get native image compiled with graalvm8-20.2
Error: Unsupported features in 5 methods
Detailed message:
Error: Frame states being merged are incompatible: unbalanced monitors - locked objects do not match
 This frame state: [locals: [1,2,3,1,_,_] stack: [7] locks: [] rethrowException]
Other frame state: [locals: [1,2,3,1,_,_] stack: [20] locks: [14 / 5] rethrowException]
Parser context: sci.impl.vars$alter_var_root.invokeStatic(vars.cljc:417) [bci: 11, intrinsic: false]
could the clj-kondo standalone.jar include your clj-reflector-java11 fix?
#2020-11-0420:02borkdudeclj-kondo only supports compiling to native with graalvm jdk11 20.2.0#2020-11-0420:04borkdudeAh I see, clj-kondo now includes sci and sci needs Clojure 1.10.2-alpha* to avoid those warnings in graalvm#2020-11-0420:05borkdude@b Is there a reason you can't make the uberjar yourself, if you already have graalvm 11 in nixos?#2020-11-0420:06bennyjust trying to cut down on the dependencies, because graal8 was based on the src release and that took 24 GB of memory to build which overwhelmed my computer and the build farm computer quite often#2020-11-0420:07bennybut yeah I could try to get leiningen and create the uberjar#2020-11-0420:07borkdudeThat would be easier I think. You could maybe just run the existing script/compile in that case#2020-11-0420:09bennyI haven't yet checked if this is so easily done because NixOS is all about purity and if leiningen grabs a lot of dependencies then it requires network access which is impure#2020-11-0420:10borkdudea PR to bring the uberjar build on circleci up to date with jdk11 + the reflector fix is also welcome#2020-11-0420:11bennyI will do that!#2020-11-0420:11borkdudeI think the sole reason it is published is the nixos builds, unless I forgot#2020-11-0420:12bennyand it's fine if the regular standalone.jar is replaced by the one that includes the java11-reflector-fix?#2020-11-0420:13borkdudeif it's only used by nixos, then I think so?#2020-11-0420:13borkdudelet's just do it. we'll change it if someone complains#2020-11-0420:13bennyI didn't know that history, I "just took over" in February because it was pretty much abandoned#2020-11-0420:14bennyI'll open a PR, thanks#2020-11-0508:39Jim NewtonWhat is the correct way to handle this warning from cl-kondo?
(defmulti rte-match
  (fn [rte _items & {:keys [promise-disjoint
                            hot-spot]}]
    (dispatch rte 'rte-match)))

(defmethod rte-match :sequential
  [pattern items & {:keys [promise-disjoint
                           hot-spot]}]
  (rte-match (rte-compile pattern) items :promise-disjoint true :hot-spot hot-spot))
It warns that promise-disjoint and hot-spot are not used in the defmulti, and that promise-disjoint is not used in the first defmethod. However, these keys ARE used in other defmethods. I'm not sure whether this is a clojure question or a clj-kondo question actually
#2020-11-0508:40Jim Newtonshouldn't the defmulti declare all the keys which methods are allowed to consume?#2020-11-0508:40delaguardono, they don’t have to#2020-11-0508:41Jim Newton"have to"? OK I agree it's not strictly necessary. but it seems to me that the defmulti should serve as documentation to applications which want to add methods. right?#2020-11-0508:41delaguardoyou can write it like this
(defmulti rte-match
  (fn [rte _items & _]
    (dispatch rte 'rte-match)))

(defmethod rte-match :sequential
  [pattern items & {:keys [hot-spot]}]
  (rte-match (rte-compile pattern) items :promise-disjoint true :hot-spot hot-spot))
#2020-11-0508:42delaguardodefmulti is a strange beast (imho) in terms of documentation#2020-11-0508:42delaguardosince dispatch function can be detached from declaration of defmulti#2020-11-0508:42Jim NewtonIf I do that, then where is the documentation for the callers of the methods to use, and where is the documentation for implementors of methods to use?#2020-11-0508:42delaguardo(defmulti foo some-dispatch-fn)#2020-11-0508:43delaguardoin a docstring after the name of defmulti#2020-11-0508:43delaguardo(defmulti foo "docstring" some-dispatch-fn)#2020-11-0508:43Jim Newtongood idea.#2020-11-0508:45Jim Newtonon the other hand, clj-kondo seems to have the feature that normal parameters which are not used can be prefixed with _ to disable the warning.
(defn foo [a b _c d] ...)
clj-kondo will not warn that _c is unused. Is there something similar for key arguments?
#2020-11-0508:45delaguardoright#2020-11-0508:46delaguardoby convention arguments beginning with _ (including single character _) are “might not be used”#2020-11-0508:46delaguardobut you still can use them in function’s body
(fn foo [_x _y] (+ _x _y))
#2020-11-0508:47Jim NewtonI see that clj-kondo fails to warn if I use an _ variable. That's unfortunate.#2020-11-0508:47delaguardo?#2020-11-0508:47Jim Newtonin Common Lisp you can mark them as the three different cases.#2020-11-0508:47Jim NewtonI.e., in CL i can declare the variable as either unused or maybe-unused#2020-11-0508:48delaguardoas I mention this is a convention not a rule in clojure#2020-11-0508:48Jim Newtonand thus if I mark something as unused, but still use it i get a welcomed warning.#2020-11-0508:48delaguardo_ or _x are just normal symbols that can be used as a names of vars#2020-11-0508:48delaguardo(defn foo [_] (inc _))#2020-11-0508:49Jim Newtonindeed, but kondo is applying some conventions to the names to aid the programmer in static analysis, right, clojure doesnt care.#2020-11-0508:50delaguardoexactly, and you always can switch this warnings on and off#2020-11-0508:54delaguardobut maybe I’m wrong, better to ask @borkdude if it is possible to turn on warning about “unused vars” beeing used#2020-11-0508:55borkdudeI’m afk today until the evening. Check config.md for documentation about config.#2020-11-0508:58delaguardoI will open an issue because there is no option (as I can see in config.md) to turn on such warnings#2020-11-0509:01borkdudeThis has already been suggested in one of the issues. Can’t really Google it on my phone :-)#2020-11-0509:02delaguardomy google fu failed me) will check one more time#2020-11-0509:03delaguardohttps://github.com/borkdude/clj-kondo/issues/861#2020-11-0509:03delaguardofound it#2020-11-0513:01Jim Newtonah that was my issue from long ago. I forgot about that. but now it rings a bell.#2020-11-0515:10Jim NewtonI looked for a bug all day. The bug occurred when I moved a bunch of functions around, basically refactoring name spaces. The problem was that when I run my tests from the lein command line they fail. But when I run them interactively the succeeded. The problem finally turned out to be I was defining the method in two different files. The defmulti is in a file whose namespace is genus and is abbreviated gns every where which requires it. The intent is that other files can add methods to gns/-disjoint?. Unfortunately two different files added the method
(defmethod gns/-disjoint :rte ...)
with two different implementations. QUESTION: Shouldn't clj-kondo warn me about this?
#2020-11-0515:16Darin Douglasson the surface that feels like a nice linter#2020-11-0515:20Jim Newtonit is perfectly legal to redefine methods. otherwise debugging would be more difficult. But static analysis should warn.#2020-11-0515:21Jim NewtonI'll file an issue.#2020-11-0515:27Jim Newtonhttps://github.com/borkdude/clj-kondo/issues/1061#2020-11-0515:28Jim Newtoneveryone should rush there and give it a thumbs up. 👍:skin-tone-2:#2020-11-0515:35delaguardoI think it doesn’t really matter where defmethod is redefining same dispatch value right now clj-kondo will not complain even about this
(defmulti foo identity)

(defmethod foo :x [_] :x)

(defmethod foo :x [_] :y)
all in the same namespace
#2020-11-0515:35Darin Douglassshould it though is the question really#2020-11-0515:36delaguardosure it is#2020-11-0515:36borkdude?#2020-11-0515:40delaguardo
(defmulti foo identity)
(defmethod foo :x [_] :x)
(defmethod foo :x [_] :y)
this example right now looks ok for clj-kondo but might be considered as perfect place for warning about defining different implementations for the same dispatch value of multi method
#2020-11-0515:57borkdudeok, makes sense#2020-11-0515:36Darin Douglassthat code above feels smelly and is more likely than not the cause of a bad copy/paste#2020-11-0515:38delaguardodon’t mind right hand side of my examples ) the important part is on the left and it is not necessary bad copy/paste but could be some leftovers after refactoring or intensive REPL usage#2020-11-0515:40Darin Douglassyeah artifacts of refactoring/updates/etc#2020-11-0515:57borkdudemakes sense#2020-11-0516:38Jim NewtonAgree that it doesn't matter where the method is defined. My comment was simply that it might be defined as a naked name in one place (defmethod foo :x ...) and as a decorated name elsewhere (defmethod mynamespace/foo :x ...) and that still deserved a complaint from kondo. in my opinion.#2020-11-0517:40benny@borkdude do you want me to create an additional circleci path to create the with-profiles standalone.jar?#2020-11-0517:42borkdude@b Just commented. I think it's better if you removed the native-image profile for the uberjar creation, since that needs JDK11 (it pulls in JDK11-specific deps)#2020-11-0517:42borkdudeBut an uberjar created with Java 8 should be compileable with Java 11, so I think then it should work#2020-11-0517:44bennyI must be blind, but there is no mention of java8 in any .circleci/config.yml#2020-11-0517:44bennyit downloads graalvm11 only#2020-11-0517:44borkdude
circleci/clojure:lein-2.8.1
has java 8 by default
#2020-11-0517:47bennythat's quite unfortunate because I had to use both profiles for it to work with native-image for me#2020-11-0517:47bennyI used the clojure:lein-2.8.1 image on my own system to generate the standalone jar and then transfer it to my real host#2020-11-0517:48bennyweird that I didn't get that error, that's why I wrote about the caching of .m2 as a potential cause#2020-11-0517:49bennybut I also build everything after I already had prepended the graalvm directory to my PATH#2020-11-0517:49borkdude@b It might be better if the native-image step on CircleCI just posted the uberjar as an artifact as well. This way you are guaranteed to use the same one#2020-11-0517:50borkdudeSo instead of in the JVM step#2020-11-0517:51bennyso sidestepping the normal jobs and creating an additional single job that does everything needed to create the standalone jar?#2020-11-0517:52borkdudecould do, but could also do it in the linux job#2020-11-0517:53borkdude@b Right now we have these files: https://app.circleci.com/pipelines/github/borkdude/clj-kondo/3030/workflows/1c2aa51c-ca4c-4c2b-a95d-d2e924909f54/jobs/11540/artifacts We could simply add the uberjar to it#2020-11-0517:53borkdudeAnd then I will post that in the github releases in the future#2020-11-0517:53bennyoh wow, I just tried to reproduce it and I found why I thought it worked in my setup: I tested the circleci steps in circleci/clojure:lein-2.9.1 instead of lein-2.8.1#2020-11-0517:53borkdudeand that one has java11 right#2020-11-0517:53bennylein-2.9.1 comes with java11 yeah#2020-11-0518:15bennyI'm using up all your circleci credits with my fails 😮#2020-11-0518:17borkdude@b
"$VERSION" -eq "linux" 
should probably be:
"$CLJ_KONDO_PLATFORM" -eq "linux" 
(not sure about -eq, I always use = for strings in bash)
#2020-11-0518:17borkdude
environment:
      LEIN_ROOT: "true"
      GRAALVM_HOME: /home/circleci/graalvm-ce-java11-20.2.0
      CLJ_KONDO_PLATFORM: linux # used in release script
      CLJ_KONDO_TEST_ENV: native
 
#2020-11-0518:17borkdudeso you were close#2020-11-0518:18bennyfair enough and you're probably also right about the bash thing, -eq is for checking return code results 😉#2020-11-0518:18borkdudebut I think it might not hurt to copy the uberjar if it's not on linux#2020-11-0518:19Michael WTechnically -eq is for checking integers, = is for strings. In bash.#2020-11-0518:19bennydo you manually download the artifacts then? I didn't want to overwrite anything in case you automatically merged all the artefacts#2020-11-0518:19borkdudeyeah, I do it manually#2020-11-0518:26borkdude@b
cp: cannot stat 'target/clj-kondo--standalone.jar': No such file or directory
  adding: clj-kondo (deflated 71%)
#2020-11-0518:26borkdudeWe might want to add set -e to the script#2020-11-0518:26bennyokay#2020-11-0518:26borkdude
set -eo pipefail
#2020-11-0518:28bennyman I don't know what I'm doing right now, sorry for not paying attention.#2020-11-0518:30bennylaptop on couch is not great for concentration#2020-11-0518:35borkdudeseems to work now right? https://app.circleci.com/pipelines/github/borkdude/clj-kondo/3034/workflows/f45a9937-a0f6-46a2-ba8d-fa517458e928/jobs/11556/artifacts#2020-11-0518:36borkdudeas a last step, I think we can now remove the uberjar from the jvm tests#2020-11-0518:37bennyI'll test the resulting standalone jar (but it looks good due to the size) and then remove the jvm uberjar creation and rewrite the commit message#2020-11-0518:38borkdude:thumbsup:#2020-11-0518:52bennylooks good, but while we're at it. should we save the earth and also zip the jar? a simple zip invocation reduces the file size by more than 50%#2020-11-0518:52borkdudea jar is already a zip file#2020-11-0518:52bennyyeah I know#2020-11-0518:53bennybut I don't know how to tweak the settings to have it user better compression#2020-11-0518:53bennywhile zip just reduces the filesize to 45%#2020-11-0518:54borkdudeI would say, let's leave it at this for now#2020-11-0518:55benny:thumbsup:#2020-11-0518:33bennysuccess!#2020-11-0520:20borkdudeMerged the first batch of checks for deps.edn to master: https://github.com/borkdude/clj-kondo/blob/a9df3965716025e93764d36100314edca30e5cee/test/clj_kondo/deps_edn_test.clj#2020-11-0619:48borkdudeI just merged exporting and importing config via the classpath to master. Docs: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#Exporting-and-importing-configuration#2020-11-0711:21borkdude@dominicm I implemented .jar caching on master#2020-11-0711:56dominicm@borkdude Ooh 😁 Do you generate a master build anywhere?#2020-11-0711:57borkdudeI will release a new version now#2020-11-0712:03borkdudeReleased.#2020-11-0712:06dominicmNice, I'll give that a go now. I'm currently working on the tool I was using this for :) Will give you some measures. This is one of the times where having an FX8350 is valuable - testing worst case performance.#2020-11-0712:19dominicm@borkdude I'm not seeing any speedup.#2020-11-0712:19borkdude@dominicm How are you linting#2020-11-0712:19borkdudeYou should explicitly use --no-warnings#2020-11-0712:20borkdudeIf you are not seeing messages about skipped jars, it doesn't#2020-11-0712:20dominicm@borkdude That made a difference. What does --no-warnings do?#2020-11-0712:21borkdude@dominicm I updated the README for that here: https://github.com/borkdude/clj-kondo/#project-setup#2020-11-0712:21dominicmIs that a new flag?#2020-11-0712:21borkdudeYes. > The --no-warnings flag indicates that clj-kondo is used to analyze sources to populate the cache. When enabled, clj-kondo will suppress warnings, skips over already linted .jar files and copies configuration from dependencies into the .clj-kondo directory (see config.md).#2020-11-0712:22dominicmHmm... I don't suppose older versions of clj-kondo would just ignore that flag?#2020-11-0712:22borkdudethey will#2020-11-0712:22dominicmOoh. Wonderful :)#2020-11-0712:23dominicmWorking wonderfully.#2020-11-0712:25dominicmDeleting lots of code, great :). On older kondos it'll hang around longer, but that's fine.#2020-11-0712:26dominicmNot much reason to not upgrade really, and I have a total of 0 users.#2020-11-0712:27dominicmI just noticed that clj-kondo doesn't warn on use of _ symbols. Surprised#2020-11-0712:28borkdudeThere's an issue for that. Recently mentioned in this channel.#2020-11-0712:27borkdudeHere's the official announcement then. Clj-kondo v2020.11.07 New: - deps.edn linting - import configs from deps - skip over already linted .jar files and more! Release notes: https://github.com/borkdude/clj-kondo/blob/master/CHANGELOG.md#v20201107 This release is funded by @cljtogether!#2020-11-0712:36dominicm
❯ clj -M:dev                                                     
Clojure 1.10.1
user=> "Elapsed time: 22009.876941 msecs"

❯ clj -M:dev
Clojure 1.10.1
user=> "Elapsed time: 607.153635 msecs"

❯ clj -M:dev
Clojure 1.10.1
user=> "Elapsed time: 574.688497 msecs"
Not bad :) I wonder where those last 600msecs are going.
#2020-11-0712:36borkdudeProbably linting src and test maybe?#2020-11-0712:37dominicmThey are tiny. Total of 52 loc#2020-11-0712:38borkdude
$ time clj-kondo --no-warnings --lint $(clojure -Spath -Sdeps '{:paths []}') --parallel
sci-0.1.0.jar was already linted, skipping
cheshire-5.10.0.jar was already linted, skipping
transit-clj-1.0.324.jar was already linted, skipping
datalog-parser-0.1.7.jar was already linted, skipping
bencode-1.1.0.jar was already linted, skipping
clojure-1.10.1.jar was already linted, skipping
edamame-0.0.11-alpha.12.jar was already linted, skipping
sci.impl.reflector-0.0.1.jar was already linted, skipping
tools.reader-1.3.2.jar was already linted, skipping
jackson-core-2.10.2.jar was already linted, skipping
jackson-dataformat-cbor-2.10.2.jar was already linted, skipping
jackson-dataformat-smile-2.10.2.jar was already linted, skipping
tigris-0.1.2.jar was already linted, skipping
transit-java-1.0.343.jar was already linted, skipping
core.specs.alpha-0.2.44.jar was already linted, skipping
spec.alpha-0.2.176.jar was already linted, skipping
commons-codec-1.10.jar was already linted, skipping
jaxb-api-2.3.0.jar was already linted, skipping
msgpack-0.6.12.jar was already linted, skipping
json-simple-1.1.1.jar was already linted, skipping
javassist-3.18.1-GA.jar was already linted, skipping
clj-kondo --no-warnings --lint $(clojure -Spath -Sdeps '{:paths []}')    0.01s  user 0.01s system 95% cpu 0.022 total
#2020-11-0712:38borkdude22 ms when linting only jars#2020-11-0712:39dominicmLinting only jars for me is 100ms :)#2020-11-0712:40borkdudenot bad either#2020-11-0712:40dominicmBut it's definitely not 500ms on src, so must be something else.#2020-11-0712:40borkdudeif you can repro anything weird with only clj-kondo, I will take a look#2020-11-0712:42dominicmI think it might be a simple 500ms overhead to http://clojure.java.sh/sh... I'm... surprised#2020-11-0712:42borkdudethat would surprise me.#2020-11-0712:43borkdudemaybe you need to do shutdown-agents#2020-11-0712:46dominicmI was being dumb, didn't activate the :dev alias when testing on the CLI.#2020-11-0712:48dominicmtools.deps.alpha takes ~400ms to lint.#2020-11-0712:50dominicmMaybe I'll try filtering to jars.#2020-11-0712:54borkdudeAh and this is a git lib right#2020-11-0712:55borkdudeI'm considering to extend this optimization to git libs but I just wanted to get this out first#2020-11-0712:55borkdudeFeel free to make an issue#2020-11-0713:19dominicmI think this is sensible for now, yeah :)#2020-11-0712:28dominicmOh nice, deps configs landed. That's awesome, I can remove that from the template too then. This makes my auto-run particularly convenient, as it'll automatically react to the inclusion of new deps on the classpath.#2020-11-0714:31borkdudeBtw, you may have to update flycheck-clj-kondo if you are using emacs integration if you want to get deps.edn linting.#2020-11-1208:50StefanHi! This morning, besides CLJ-Kondo also VSCode was updated. Now I’m getting this error:
Exception in thread "main" java.lang.UnsupportedClassVersionError: clj_kondo/lsp_server/main : Unsupported major.minor version 52.0
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:808)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:443)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:65)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:349)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:348)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:430)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:329)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:363)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:588)
[Info  - 9:42:46 AM] Connection to server got closed. Server will restart.
Has anyone else also seen it? My colleague (who is on Windows, I’m on Mac) does not have this issue apparently…
#2020-11-1208:51borkdudehmm, this might be due to me accidentally using Java 11 for deployment? But then I would have expected version 55.0 not being supported, since 52.0 is the old one#2020-11-1208:52borkdudeAre you using Java 1.7 or something on your system?#2020-11-1209:49borkdude^ @stefan.van.den.oord#2020-11-1209:49Stefan@borkdude I’m using java 8 for this (but I also have java 7 around)#2020-11-1209:50borkdude
Java SE 8 = 52
Java SE 7 = 51
https://stackoverflow.com/questions/22489398/unsupported-major-minor-version-52-0 My explanation would be that java 7 is on your path and this gets used by VScode
#2020-11-1209:53StefanI’m using asdf-vm so “that should not be possible” 😉 But your reasoning is correct. I’ll see if I can find out what vscode is using. But does your release explain that this now happens for the first time then?#2020-11-1209:55borkdudeCould happen when the Java compiler emits bytecode that's only supported by Java 8 possibly? And it didn't before because it wasn't necessary? Dunno. Maybe you can type java -version in a vscode terminal#2020-11-1209:55Stefanopenjdk version “1.8.0_265” OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_265-b01) OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.265-b01, mixed mode)#2020-11-1209:58pezThere could also be that Calva’s jackInEnv setting is in play, @stefan.van.den.oord.#2020-11-1209:58borkdude
$ file ./clj_kondo/core__init.class
./clj_kondo/core__init.class: compiled Java class data, version 52.0 (Java 1.8)
#2020-11-1209:59borkdudeseems ok#2020-11-1209:59Stefan@pez Just defaults there…#2020-11-1210:00borkdudeI don't have any other explanation than that Java 7 or older is invoked. Maybe remove it from your system and try again.#2020-11-1210:02StefanI can try indeed. It won’t be a solution though because java7 is required for the product I’m developing on. 😞#2020-11-1210:06borkdudeEither that or fix the path issue that is causing java7 to take precedence. Or make a PR that runs the clj-kondo server in a docker container ;) (Don't know if that's a good idea or not)#2020-11-1210:08StefanI first need to understand why this broke. Java 7 is not on my path normally, thanks to asdf-vm. Tuesday it still worked.#2020-11-1210:10borkdudeYou could try to test if the older version of clj-kondo from the marketplace does work for you.#2020-11-1210:19StefanAlready did, same problem 😞 It does seem to be a local issue on my machine.#2020-11-1210:20StefanRemoving java 7 fixes it, so definitely local issue.#2020-11-1214:45StefanOh wow that was an interesting corner case. Using asdf-vm the required versions of all tools can be set on a per-directory basis. The global default is java 8, and in that one project I locally set it to java 7. When I open a terminal, it will use the default and all is fine. In this specific case, I happened to have shut down my mac with an open terminal window in that specific folder. After rebooting, the apps got automatically relaunched, and iTerm happily created the terminal in that folder again, causing it to default to Java 7. Pff. Anyway, solved. Thanks!#2020-11-1302:20didibusI'm using (create-ns) and (alias) manually to create some namespaces only for the purpose of spec. Wonder if there is a way I could do it so clj-kondo wouldn't show warning Unresolved namespace marketplace. Are you missing a require? (clj-kondo-clj)#2020-11-1303:37dominicm@didibus are they top level calls?#2020-11-1308:08didibusNo they arn't.#2020-11-1308:09didibusThough I could switch the function to a macro that returned an (alias 'foo 'bar) if that can help#2020-11-1308:09dominicm@didibus are they dynamic?#2020-11-1308:09dominicmOr maybe they can't be#2020-11-1308:10didibusThey're not dynamic. Like the namespace is in the code. I wrap a call to create-ns and alias in a function. And I call that function with a hard-coded symbol#2020-11-1308:11didibusMaybe I could hook into clj-kondo and add symbols passed too my custom function to it's set of known alias? Is that possible?#2020-11-1308:20dominicmhttps://github.com/borkdude/clj-kondo/blob/9aaee5023a5da511cedd3b77bd64a35a51636416/src/clj_kondo/impl/analyzer.clj#L701 alias is supported already#2020-11-1308:20dominicmThe problem I think you have is the function.#2020-11-1308:21dominicmIt's worth testing with the function inlined to see if the magic already works.#2020-11-1320:56didibusHum, this makes me wonder, does inlining work with clj-kondo? Like with definline or :inline meta ?#2020-11-1320:58didibusDoesn't look like it does#2020-11-1308:21dominicmIf it does, then I'd try hooks potentially.#2020-11-1308:27dominicm@didibus
(ns foo)

(create-ns 'com.bar.baz)
(alias 'bar 'com.bar.baz)

::bar/foo
This lints fine. So I'd try hooks.
#2020-11-1308:32borkdudeyes, a hook could work. but clj-kondo could also be tweaked to recognize the (alias 'foo (create-ns 'bar)) pattern is that is used a lot#2020-11-1320:47didibusI'm doing:
(create-ns ns)
  (alias alias-sym ns)
#2020-11-1320:48didibusBut I have this wrapped in a utility function which is in another namespace, which I call like so:
(defalias 'alias 'namespace)
#2020-11-1308:32borkdudeand you can also do that yourself via a hook right now. or use #_{:clj-kondo/ignore [:unresolved-namespace]}. This is only needed in the first occurrence.#2020-11-1311:24amorokhhi, I get error indications from clj-kondo when I use async/alt! in clojurescript, the errors report the binding symbol in a result-expression as unresolved symbol, anybody else seen this? works fine in clojure..#2020-11-1311:24borkdudeCan you make a small .cljs file / snippet that shows the problem?#2020-11-1311:31amorokhhmm, I’m not really familiar with slack and how to send snippets, that was not what I intended#2020-11-1311:32amorokh
(ns repro
  (:require-macros [cljs.core.async.macros :refer [go alt!]])
  (:require [clojure.core.async :as async]))

(let [ch (async/chan)]
  (go
    (alt!
      ch ([value]
          (println value)))))
#2020-11-1311:32amorokhthat was better#2020-11-1311:33amorokhwhen I have that code in a cljs file in VS Code, I get error squiggly on the value binding symbol#2020-11-1311:34borkdudeYeah, I see. If you write:
(let [ch (async/chan)]
  (go
    (async/alt!
      ch ([value]
          (println value)))))
then it goes away, but I'm not sure if that's valid in CLJS
#2020-11-1311:36borkdudeI will ask in #clojurescript#2020-11-1311:40amorokhok, so it’s related to :require-macros ?#2020-11-1311:40borkdudeclj-kondo understands clojure.core.async/alt but it doesn't have a special rule for understanding the CLJS way of using that#2020-11-1311:40borkdudebut if you're lucky this is fixed in newer version of CLJS#2020-11-1311:40amorokhI see#2020-11-1311:41amorokhthanks#2020-11-1311:41borkdudeYou can fix it now with this config:
(ns repro
  {:clj-kondo/config '{:lint-as {cljs.core.async.macros/alt! clojure.core.async/alt!}}}
  (:require-macros [cljs.core.async.macros :refer [go alt!]])
  (:require [clojure.core.async :as async]))

(let [ch (async/chan)]
  (go
    (alt!
      ch ([value]
          (println value)))))
#2020-11-1311:42borkdudeso:
{:lint-as {cljs.core.async.macros/alt! clojure.core.async/alt!}}
#2020-11-1311:42borkdudeMaybe post that in an issue and then we can include that in clj-kondo itself#2020-11-1311:43amorokhok, thanks again#2020-11-1312:01amorokhI guess that an issue for this is unnecessary then?#2020-11-1312:07borkdudeyeah, I think so#2020-11-1321:18didibusManaged to fix it with :lint-as my/fn clojure.core/alias That was easy 😄#2020-11-1321:21didibusI had assumed :lint-as was only for macros for some reason, but ya, happy to see it works for functions as well#2020-11-1321:24borkdudeyeah, clj-kondo doesn't care about macro or function, it only cares about the surface form#2020-11-1321:24didibusAnother question, for Alias consistency it seems you need to configure it. Would there not be a way that it just complained on alias that differed in a code base? Like if I had two namespace, one where foo.bar is foo and another where foo.bar is bar, then both alias would show a warning saying they are inconsistent with one another?#2020-11-1321:26borkdude@didibus That has come up in the issue when writing that linter. The reason we didn't do that is that currently clj-kondo doesn't read information about other namespaces other than vars from the cache. And you would have to make a choice either way: like what if two namespaces have str and two other namespaces have s. You would have to specify one of both in the config then anyway. So it just made the most sense to just start out with a baseline#2020-11-1321:27borkdudeYou can retrieve the aliases from all namespaces from the analysis config yourself and then spit out some baseline, probably#2020-11-1321:31didibusThat makes sense, though, I think an automatic one would be much more useful. Generally, I don't care if its s or str, but I care that whichever it is is the same everywhere. So I'd expect that the first one someone uses would become the standard, as the next person to alias it would see the warning: Inconsistent alias, aliased as s in foo And so they'd fix their inconsistent usage. But I recon the added complexity of doing so due to needing info from other namespaces for it.#2020-11-1321:34borkdudeThe problem is that this requires knowledge of an entire code-base, while linting only one file (in editor usage)#2020-11-1321:35borkdudeYou can write such a linter yourself based on the analysis output of course, but then you would not see it in your editor#2020-11-1321:35borkdudeMaybe useful for CI#2020-11-1321:52didibusHum, ya that's fair. Not something the cache could make use of?#2020-11-1322:01borkdudeWe could write to a special cache file that this linter could read from which would be an index of namespace (clojure.string) -> frequency table of aliases, or something? I haven't thought this through in detail, but feel free to think more about it.#2020-11-1322:02didibusSeed is planted 😛 Its not my most important concern, just thought about it as I was reading on the linter#2020-11-1322:15seancorfieldRe: namespace aliases -- is there a linter for sanity-checking the alias (in the absence of configuration) based on the common guideline that a namespace should be aliased to the last segment of its name (if that wouldn't be ambiguous in a file)?#2020-11-1322:15seancorfieldIs that a common enough guideline to be worth implementing?#2020-11-1322:17seancorfieldObviously there are exceptions (`clojure.spec.alpha :as s` and clojure.string :as str are the most common I've seen in books and tutorials and it seems that datomic.client.api :as d is canonical).#2020-11-1322:17seancorfieldMaybe some built-in (overridable) defaults for common nses?#2020-11-1322:18borkdudeyeah, there could be some predicate (that can be executed with sci) to determine the desired alias#2020-11-1322:18borkdudewith a good built-in default predicate#2020-11-1322:18borkdudethe linter already supports a config, which would be the overrides#2020-11-1322:20borkdude> is there a linter for sanity-checking the alias No > Is that a common enough guideline to be worth implementing? Possibly#2020-11-1322:20borkdudeI tend to do edamame.core :as e as well#2020-11-1322:21borkdudeor sci.core :as sci, so I think it would maybe be hard to come up with a predicate that would satisfy the entire community#2020-11-1322:23borkdudeAlso, the function would have to give a unique answer for a given lib. What if there is already an e in the config, what would it recommend: ed, e2 ?#2020-11-1322:26seancorfieldI'll give it some thought, and see if I can come up with a good heuristic. In the presence of ambiguity -- either against the config or other aliases in the current ns -- just not running the check would seem to be the safest option.#2020-11-1421:05lvhIs it possible to teach clj-kondo that a particular macro defines many names, and so those names are no longer undefined (without declare ), e.g. : https://github.com/lvh/caesium/pull/74/files#diff-65e89161949c41707e1727f4a784969c02b9626b37ac949f704efcd26f7a9519R6#2020-11-1421:06lvh(as specified in that PR, it works: clj-kondo doesn't complain, because there's a declare, I'm asking if there's a magic configuration incantation that makes it unnecessary)#2020-11-1421:12borkdude@lvh if the macro is syntactically similar to a core one, then you can :lint-as but for this macro that doesn't apply. E.g. if defconsts was varargs like declare then :lint-as with clojure.core/declare would work. The other way is to write a hook to rewrite your function call to multiple top-level defs or just declare .#2020-11-1421:13borkdudeThe hook code for this macro would be pretty straightforward.#2020-11-1421:20borkdude@lvh This works:
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "b2d0ddc0d9d6c7d6d7f2fff0e28082838b"}, :content ("[email protected]")}
#2020-11-1421:44lvhAwesome, thanks!#2020-11-1421:45lvhIt's internal so I think I'll just change the API to take varargs and lint it like declare#2020-11-1421:45lvhmuch appreciated!#2020-11-1423:50didibusI have an overloaded function, it has a 1-ary and a 2-ary version. I need to specify a :lint-as that is different for each. Is that something that clj-kondo support?#2020-11-1511:38borkdudeThis isn't possible using lint-as. I think you would need to write a hook to support this#2020-11-1623:27didibusCool, thx#2020-11-1902:02didibusIs there a way when I write my hook I can test it at the REPL? Like can I call api/something clojure-code-to-lint which will parse the clojure-code-to-lint and call my hook with the rewrite-clj node for it?#2020-11-1902:19didibusI think using {:node (parse-string ...)} from the utils namespace does the trick#2020-11-1902:03didibusAlso, I'm only seeing a clj-kondo.impl.hooks in the Jar, but the doc says my hook needs to require clj-kondo.hooks-api#2020-11-1902:22didibusHum, and they seem to contain different functions as well#2020-11-1904:39didibusOk, so it seems in the Jar clj-kondo.impl.utils is the same as clj-kondo.hooks-api inside sci when acutally running through clj-kondo#2020-11-1904:39didibusSo now, my last issue is, how do you create a QuoteNode? It doesn't seem that there is a util for that?#2020-11-1904:40didibusMy hook needs to rewrite things with a quoted symbol?#2020-11-1904:40didibusIf I just use token node, I get: "Unable to resolve symbol" which makes sense, since its supposed to be a quoted symbol#2020-11-1904:57didibusI tried to use list-node with quote but it doesn't help me, because this:
(do (alias (quote app) (quote app)))

::app/db
Doesn't lint, it seems the alias linter doesn't work if using (quote app) instead of 'app
#2020-11-1910:05borkdudeWe should support that in clj-kondo. Please post an issue, I will mark it as high priority and pick it up before next release.#2020-11-1920:01didibusDone: https://github.com/borkdude/clj-kondo/issues/1074#2020-11-1904:58didibusWhich I think is cause they are parsed differently, 'app results in a QuoteNode, while (quote app) result in a ListNode#2020-11-1906:02sogaiufor quoting i think this might work: https://github.com/sogaiu/libpython-clj/blob/dbb0e36a5211cfbfac9a34c4eb5d973f55d2c61c/resources/clj-kondo.exports/clj-python/libpython-clj/hooks/libpython_clj/require/import_python.clj#L38#2020-11-1907:14didibusThat didn't seem to work for alias#2020-11-1907:15didibusBut if the require linter works with it... Hum maybe I could rewrite my hook to a require instead of an alias.#2020-11-1910:06borkdudeThat could work, nonetheless we should support this for alias as well#2020-11-1922:04didibusSwitching to require worked. I still cut an issue for alias#2020-11-1922:06borkdudeThanks, will be fixed.#2020-11-1906:03sogaiubut may be that's not going to help in your situation#2020-11-1906:04sogaiufor debugging, i've been copying what @lee did here: https://github.com/lread/rewrite-cljc-playground/blob/09882e1244a8c12879ef8c1e6872724748e7914b/.clj-kondo/hooks/rewrite_cljc/potemkin/import_vars_with_mods.clj#L60-L61 then invoke clj-kondo from the command line#2020-11-1910:06borkdude@U0K064KQV Yes, prn/println is good for debugging. For running actual tests, I recommend just linting source with the hook and write tests based on the linter results#2020-11-1919:50didibusI found I can just swap the require for the clj-kondo.impl.utils namespace at the REPL, and call my hook with parse-string wrapped in a {:node} map and it works. As long I make sure I don't use anything in utils that sci doesn't include in api.#2020-11-1920:09borkdudeWe could expose a JVM version of the hooks API for testing as well.#2020-11-1920:15didibusI think that be useful. It wasn't too hard for me to swap the namespace require back and forth, but still a bit annoying. Also, could be nice to have a parse-for-hook util or something. Which does: ({:node (parse-string string-form)}) or something similar. Though again, it wasn't very hard for me to just wrap parse-string in it.#2020-11-1923:03adambrosif i have an empty (or) i get this error at the ns decl Wrong number of args (0) passed to: clj-kondo.impl.types.utils/union-type is this known about and i just need to upgrade?#2020-11-1923:04borkdudeupgrade, it's already fixed#2020-11-1923:04adambrosah found the issue, shoulda checked first#2020-11-2017:18mynomotoWhen using several :config-paths is it expected that configs for :unresolved-symbol, :deprecated-var, :output to merge/concatenate?#2020-11-2017:27borkdudeyes, all the configs merge#2020-11-2017:28borkdudedoes this give a problem?#2020-11-2017:28borkdudeyou can prevent merging / override by putting ^:replace on a map value#2020-11-2017:29borkdude^ @mynomoto#2020-11-2017:35mynomotoI may be doing something wrong then. I have a monorepo and on the toplevel I added a config to make my editor happy. I was trying to only have :config-paths pointing to the subprojects configs. But when I deleted the rest of the configuration on the toplevel warnings started to show on the editor.#2020-11-2017:38borkdude@mynomoto if you could make a small github repo that mimics your problem, I'd be happy to take a look. You can probably make deliberate mistakes in the config and they will get logged as warnings, to see if they are being processed at all#2020-11-2017:39borkdude@mynomoto Note that clj-kondo will only look up one time for a .clj-kondo directory. .clj-kondo directories on a higher level won't be seen#2020-11-2017:39borkdudeso if you have a .clj-kondo in your subrepo and one on the top-level, only the subrepo one will be considered#2020-11-2017:41mynomotoIs there a way to see the config that is being used after the :config-paths are processed?#2020-11-2017:42borkdudenot currently, but you could try with clj-kondo in the JVM and stick a println somewhere in clj-kondo/impl/config.clj
#2020-11-2017:43mynomotoOk, thanks. I will try to investigate/reproduce on a small project.#2020-11-2017:44borkdudeoh btw, you might be able to see the config when you use clj-kondo.core#2020-11-2017:44borkdudeas a JVM lib#2020-11-2017:44borkdudeas output from run!#2020-11-2017:46borkdude
user=> (require '[clj-kondo.core :as k])
nil
user=> (keys (k/run! {:lint ["src"]}))
(:findings :config :summary)
^ @mynomoto
#2020-11-2018:02mynomotoOk, thanks. I will try that.#2020-11-2109:37ikitommithere is no way to declare a “vector of maps” with clj-kondo type system? seems that the collections have just type :vector.#2020-11-2109:39ikitommiwould be happy to emit {:op :vector :elements {:op :keys, :req {:id :int}} for clj-kondo#2020-11-2109:39borkdudecurrently not supported#2020-11-2109:40borkdudeit's not a higher order type system#2020-11-2109:40borkdudethe likelihood of catching these types of errors with static analysis is also rather small I'd say#2020-11-2109:41borkdudebecause clj-kondo can only look at the literal forms#2020-11-3018:22didibusHum, I thought it used type hints as well no? Wouldn't it catch:
(def ^String foo (get-foo-from-config))

(+ 10 foo)
#2020-11-3018:29borkdudeIt could catch that, but currently it doesn't look at var types, only function return values.#2020-11-3018:30borkdudebut the example ikitommi was referring to was a vector of maps#2020-11-3018:30borkdudeand clj-kondo only cares about the outer type#2020-11-3018:32didibusAh I see. Ya, I know no support for generic types yet. I was more commenting to the literal comment. So I guess it looks at literal and function return types for now? Which is slightly more than just literals 😛#2020-11-3018:32didibusBut I assumed it was looking at Var and local binding types as well.#2020-11-3018:34borkdudeyes, it does. this gives a warning:
(defn foo ^String []) (inc (foo))
#2020-11-2109:41ikitommitrue that, most likely not declared as literal, right#2020-11-2110:13ikitommiI believe “maybe string” is :nilable/string, is there a way to say “maybe map”?#2020-11-2110:14borkdudedoes :nilable/map work? :)#2020-11-2110:15borkdudeelse #{nil :map} will also work#2020-11-2110:21ikitommioh, I was thinking about a :keys thing. but #{nil {:op :keys, :req {:id :int}}} is ok?#2020-11-2110:22borkdudeit seems that if it can be nil, then all keys are optional is the same?#2020-11-2110:22borkdudeoh, op keys assumes it is a map and not nil, I see#2020-11-2111:23borkdudeIf someone is looking for some OSS issues to work on, here's a list: https://gist.github.com/borkdude/18af5d96c6465ce64144f03636fda3dc#2020-11-2121:59dominicmI find the "feature" template a little awkward for suggesting new lints for clj-kondo. I don't know how to phrase a "problem statement" in the way it seems to suggest. Nor do I have an idea for what to put in for alternatives.#2020-11-2122:01borkdudeWell, it would be nice if a linting rule solves a particular problem, else it's pretty useless right? ;)#2020-11-2122:03borkdudeBut feel free to discuss new rules here first, then we can always decide if this should become an issue or not#2020-11-2122:08borkdudeAh I see you already posted them. One of them was already implemented. Nice :)#2020-11-2209:00dominicm@borkdude I definitely don't have alternatives when I'm suggesting a lint rule though :). Other than writing better code.#2020-11-2209:35borkdude@dominicm For example with this issue: https://github.com/borkdude/clj-kondo/issues/1076 You suggest a specific linting rule, but an alternative could have been a more general rule like the existing :single-key-in. That linter came from a discussion that we had while going through a couple of alternatives and imo is better than specific linters for :get-in, :assoc-in etc.#2020-11-2209:37dominicmAh. My creativity limits me here I'm afraid :)#2020-11-2209:38borkdudeThat's why it can be useful to throw ideas around here first. If seancorfield (I think it was him) hadn't suggested it, maybe it would have become the more specific one :)#2020-11-2209:59dominicmHappy to do that. I did start to, but didn't want to create noise.#2020-11-2210:00borkdudePersonally I don't mind, certainly not if it contributes to the quality of clj-kondo#2020-11-2309:53niveauverleihI'm trying to install the clj-kondo lsp server again. I got it running in the past, but this time I hit a problem. First, when I run java -jar clj-kondo-lsp-server.jar the process starts but it does give any output. Is that normal? Second, in spacemacs I get an error LSP :: Connected to [clojure-lsp:21508 status:starting]. LSP :: clojure-lsp has exited (exited abnormally with code 1) Server clojure-lsp:21508 status:starting exited with status exit. Do you want to restart it? (y or n) n I don't know why it talks about clojure-lsp, I configured it as described on your github to run the clj-kondo-lsp-server.jar. Any ideas?#2020-11-2309:55borkdude> the process starts but it does give any output. Is that normal? Yes, it just waits for a connection This seems more like a configuration issue on your end than an issue with clj-kondo LSP since it doesn't not have any dependency on clojure-lsp#2020-11-2310:22niveauverleihOk, I'll check.#2020-11-2314:43practicalli-johnThis is the config I used previously (It has been a while since I tested it). https://github.com/practicalli/spacemacs.d/blob/live/init.el#L974-L987 The only difference is I use a script called clojure-lsp-server-clj-kondo to wrap the java command to run the LSP server. If you dont fix it I can try this again later today.#2020-11-2319:54niveauverleihThanks, I solved it. In the dotspacemacs file I had to put a complete path from root to the jar iso a relative path from home.#2020-11-2322:23practicalli-johnHaving to use the full path is why I used a script instead, to make the Emacs config more portable#2020-11-2314:48practicalli-johnFYI. The https://github.com/marketplace/actions/setup-clj-kondo GitHub actions for clj-kondo was updated 13 days ago to resolve the deprecation of add-paths in GitHub actions. I just updated and the new version, - uses: DeLaGuardo/ is working well. Thanks.#2020-11-2319:54niveauverleihThanks, I solved it. In the dotspacemacs file I had to put a complete path from root to the jar iso a relative path from home.#2020-11-2811:59davehey there, i installed clj-kondo on a shared ubuntu server i don’t have sudo access to. the install seemed fine with using the —dir command but when i try to run it i get this error: clj-kondo: error while loading shared libraries: cannot make segment writable for relocation: Permission denied#2020-11-2812:01borkdude@tech Maybe you could download the bash script and debug it: https://github.com/borkdude/clj-kondo/blob/master/script/install-clj-kondo#2020-11-2812:06borkdudeAll the installer does is basically download the zip file, extract it and put the binary on your path#2020-11-2812:06davethe install script worked ok... i was running just clj-kondo -h#2020-11-2812:06davewhen i got the error#2020-11-2812:07borkdudeoh, that's weird. I'm not sure what's going on there#2020-11-2812:08davemust be some directory it wants... not sure either. i can keep poking around at it#2020-11-2812:08borkdude@tech after some googling I found this: https://linux-tips.com/t/cannot-make-segment-writable-for-relocation-error/481#2020-11-2812:11daveoh interesting, doubt i will be able to run that since i don’t have sudo on this shared machine#2020-11-2812:11borkdudeMaybe you can run clj-kondo via docker or via the JVM version#2020-11-2812:13davemight be able to install a local JVM too with jenv#2020-11-2815:10Ben SlessIs there a way after writing hooks for a library to expose them to other kondo users who use macros the from my library?#2020-11-2815:12borkdude@ben.sless Yes. This is a new feature that's been implemented since the previous release: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2020-11-2815:12Ben SlessExcellent, thanks 🙏#2020-11-2815:44BuidlerI'm trying to add the fulcro config. I followed the instructions at https://github.com/clj-kondo/config, but there is no .clj-kondo/configs/ folder present after the clojure -A:clj-kondo/config --lib fulcro command appears to complete successfully.#2020-11-2815:47borkdude@randumbo Did you have a .clj-kondo directory prior to that?#2020-11-2815:47BuidlerYes, I did.#2020-11-2815:51borkdudeOK, I see there's a bug in there. Let me fix it#2020-11-2815:52borkdudeFixed.#2020-11-2815:57BuidlerThanks very much. Folder is there now. I still see warnings show up in places like defmutation, where it shows error| unresolved symbol action and other similar warnings. My understanding was that adding the fulcro configs should eliminate some or all of those warnings.#2020-11-2815:59borkdudeAh. Currently the fulcro support is a bit sparse. It only contains:
{:lint-as {com.fulcrologic.fulcro.components/defsc clojure.core/defn}}
#2020-11-2816:01borkdudeBut the config lib is open for contributions so if more people find out the right config, everyone will profit.#2020-11-2816:01borkdudeI'm not using fulcro myself at the moment, so I have no idea how the API works#2020-11-2816:02BuidlerGot it. Appreciate the help. I think I saw a few mentions in the Fulcro docs about setting this sort of thing up in Cursive. I'll see if I can copy it over.#2020-11-2816:03borkdudePeople could also contribute the config to fulcro itself. It can then be imported from the classpath: https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2020-11-2816:39jkrasnayIs there a good way to configure as-> to not trigger an error? I’ve tried {:lint-as {clojure.core/as-> clojure.core/->}} but it still flags the first are to as-> as an unresolved symbol.#2020-11-2816:42borkdude@jkrasnay as-> should be fully supported. can you please post a repro of the your problem as a standalone example?#2020-11-2816:43borkdudeAlso please specify which version of clj-kondo you are using#2020-11-2816:45jkrasnayOh, I had the args to as-> reversed 😊 .#2020-11-2816:47jkrasnayclj-kondo, just doin’ its job!#2020-11-2916:31ikitommimalli function schemas can now be used to emit clj-kondo :type-mismatch config: https://github.com/metosin/malli#clj-kondo#2020-11-2916:34borkdudeAmazing!#2020-11-3022:14lreadHeyo! I just learned that defprotocol https://clojure.atlassian.net/browse/CLJ-888. Should clj-kondo help out with a linter here? If so, want me to raise a git issue?#2020-11-3022:15borkdudeyes please#2020-11-3022:29lreadCool, thanks, raised: https://github.com/borkdude/clj-kondo/issues/1082#2020-11-3022:30borkdude@lee It would help me if you could also make a suggestion for the specific error message, it will make me think less#2020-11-3022:30lreadSure thing.#2020-11-3022:30borkdudeThanks!#2020-11-3022:31borkdudeI'll also label it as PR welcome, but I'll get to it at some point if nobody else will take it#2020-11-3022:33lreadI’m distractible to a fault, so I’d better not take it on until I make some progress on rewrite-cljc. simple_smile#2020-11-3022:34borkdudeAnd I wouldn't want to distract you from that :)#2020-11-3022:35lreadAlso… noticed that clj-kondo doesn’t seem to validate defrecord functions? Maybe that’s covered by https://github.com/borkdude/clj-kondo/issues/140#2020-11-3022:36borkdudeyes, that's a TODO. I run into it myself sometimes, but quite rarely :)#2020-11-3022:36lreadYeah, rewrite-clj uses protocols and records and that’s the only reason I noticed.#2020-11-3022:36borkdudeI'll put that in the high priority column, it's been sitting there long enough ;)#2020-12-0116:15dehlihello 👋 is it possible to have kondo lint for line lengths? i’d like to enforce a character limit#2020-12-0116:18borkdudecurrently clj-kondo is not doing anything with formatting and whitespace related information. there might be tools that are more focused on that like https://github.com/greglook/cljstyle#2020-12-0116:24borkdude@dehli or you can write a simple babashka script:
$ cat README.md | bb -i -e '(run! (fn [[i l]] (when (> (count l) 80) (println "Line" i "is too long"))) (map vector (range) *input*))'
Line 13 is too long
Line 19 is too long
Line 21 is too long
Line 46 is too long
Line 71 is too long
#2020-12-0116:24dehliawesome, thanks so much! i love babashka 🙂#2020-12-0116:24borkdudeYou could even make that spit out line/col info so you can hook it up to flycheck#2020-12-0220:38borkdudeI have started the tedious task of documenting all available linters, their key in the configuration, the message that is typically printed, etc. https://github.com/borkdude/clj-kondo/blob/linter-docs/doc/config.md#available-linters Still work in progress. Feedback on this is welcome, as always.#2020-12-0322:39devnAsking here because it looks like clojure-lsp has a few recent mentions in this channel. I am using clojure-lsp with emacs. Am I missing something, or does rename not work? The renames occur, but the files aren’t automatically saved.#2020-12-0322:40devnSo for example, if I run a rename for foo-bar to bar-baz, the changes are made, but none of the affected files are saved.#2020-12-0322:42borkdude@devn I think #lsp is the channel to ask, but if anyone here knows the answer, feel free to reply.#2020-12-0322:42devnYeah, was looking for #clojure-lsp, but joined #lsp and also posted there.#2020-12-0322:43borkdudeInterestingly #calva is also looking into adopting clojure-lsp#2020-12-0322:44ericdalloJust answered you on #lsp 😉#2020-12-0413:30Adrian Smithhey I'm trying to play with the malli intergration, I'm using their latest commit in my deps, that has generated a .clj-kondo in my project with configuration for the file I'm testing, I'm using java -jar /blah/blah/clj-kondo-lsp-server-2020.11.07-standalone.jar in intellji and I'm getting other reporting for this file like (inc "broken") but not for the given malli plus example#2020-12-0413:33borkdude@sfyire Probably best to ask in #malli#2020-12-0422:59borkdudeCompleted the list of all available linters here: https://github.com/borkdude/clj-kondo/blob/master/doc/linters.md#2020-12-0720:33didibusLooks great! And now there's a place to document new ones as they are added too! Awesome#2020-12-0716:22dominicmFor editor integration, is it a good idea to cd to the closest parent directory containing .clj-kondo if it's present?#2020-12-0716:45borkdudedoesn't matter, clj-kondo will do that search itself#2020-12-0717:47dominicmCool 😎#2020-12-0817:58tvaughanI'm trying to come up with an appropriate clj-kondo config for Fulcro mutations, https://book.fulcrologic.com/#_mutations. Specifically this form:
(defmutation add-person [params]
  (action [env] ...)
  (remote [env] ...)
  (rest [env] ...)
  (ok-action [env] ...)
  (error-action [env] ...))
Currently my config looks like:
{:lint-as
 {clojure.test.check.properties/for-all clojure.core/let
  com.fulcrologic.fulcro.components/defsc clojure.core/defn
  com.fulcrologic.fulcro.mutations/defmutation clojure.core/defn
  com.wsscode.pathom.connect/defresolver clojure.core/defn}
 :linters
 {:unresolved-symbol
  {:exclude
   [(com.fulcrologic.fulcro.mutations/defmutation [action error-action ok-action remote])]}}}}
This works, but I also want to have action, error-action, etc. treated like defn too. Is this possible?
#2020-12-0822:06borkdudeI activated discussions on clj-kondo: https://github.com/borkdude/clj-kondo/discussions. Nice way for archiving Q/A.#2020-12-0822:08borkdude@tvaughan Hmm, that looks similar to defprotocol or defrecord but not quite. I think your best best is to exclude all unresolved symbols or better, write a hook for fulcro and submit it to https://github.com/clj-kondo/config or the fulcro repo itself (https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration)#2020-12-0823:35tvaughanLooks like I'll need to write a hook. Thanks for the pointer @borkdude#2020-12-0909:59Aleksander Rendtslev@tvaughan let me know if you're jamming on this. I might take a stab at it today with the documentation borkdude posted below, but you'll probably get there faster if you're going for it#2020-12-0911:19tvaughanHey @U01DH13SK8E I won’t get to this until next week. Please go for it. I’ll be happy to play tester if you’d like #2020-12-0909:56Aleksander RendtslevSweet! Just while I was looking for it. I was about to try to write it out, but I'm still pretty new to clojure. So i was scratching my head a little on this one (the rum hook does look like a good place to start though)#2020-12-0909:57borkdudeLet me know if you need any help or have any questions#2020-12-0909:57borkdudeThe docs for hooks are here: https://github.com/borkdude/clj-kondo/blob/master/doc/hooks.md#2020-12-0920:19seancorfield@borkdude Just spotted this in the analysis of deps.edn:
#:worldsingles{worldsingles-test
                  #:local{:root "../worldsingles-test"}}
and clj-kondo flags worldsingles-test as being an unqualified lib name (which it isn't). I guess clj-kondo isn't reading namespaced-maps correctly?
#2020-12-0920:20borkdudecrap. I just pushed the button for release ;)#2020-12-0920:20seancorfieldAnd it actually recommends changing the above to this, which is definitely wrong:
{worldsingles-test {:local/root "../worldsingles-test"}}/{worldsingles-test {:local/root "../worldsingles-test"}}
#2020-12-0920:21borkdude@lee ^ interesting issue with namespaced maps in rewrite-clj wrt analysis..#2020-12-0920:21borkdudeyes, that's because it doesn't look at a namespaced map like it should.#2020-12-0920:21borkdudeissue welcome#2020-12-0920:21borkdudeI'll fix it in the next release, I just hit the release button#2020-12-0920:25lreadInteresting, thanks for the ping! I should have a look at how clj-kondo is using rewrite-clj here and make sure we are properly covered for rewrite-cljc.#2020-12-0920:26borkdudeIt could in fact be a bug in my own fork of rewrite-clj now I think about it. I'll hold off on releasing clj-kondo for today and take a look.#2020-12-0920:27lreadIn any case, I’m interested to learn more. I’ll be lurking! simple_smile#2020-12-0920:28borkdudeI'm calling sexpr on those nodes... and probably my version of sexpr for this thing doesn't work correctly... https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/linters/deps_edn.clj#2020-12-0920:29borkdudehmm, it does appear to work:
user=> (n/sexpr (p/parse-string "#:foo{:a 1}"))
#:foo{:a 1}
#2020-12-0920:29borkdudeThen maybe the bug is in the deps_edn.clj code itself.#2020-12-0920:31lreadyeah, namespaced element support is weak in rewrite-clj but my notes say that particular case is covered.#2020-12-0920:32borkdudeHmm, this looks wrong:
user=> (n/sexpr (p/parse-string "#:worldsingles{worldsingles-test #:local{:root \"../worldsingles-test\"}}"))
{worldsingles-test #:local{:root "../worldsingles-test"}}
#2020-12-0920:33borkdudeIt appears to go wrong when the map has symbols:
user=> (n/sexpr (p/parse-string "#:foo{x 1}"))
{x 1}
#2020-12-0920:35borkdudeI have never seen this case before. TIL.#2020-12-0920:35lreadBut symbols shouldn’t be namespaced, only keywords, right?#2020-12-0920:36borkdude
user=> (keys (edn/read-string "#:foo{x 1}"))
(foo/x)
#2020-12-0920:36lreadhmmm#2020-12-0920:36borkdudeotoh:
user=> (keys (edn/read-string "#:foo{\"x\" 1}"))
("x")
#2020-12-0920:37borkdude@lee does rewrite-cljc do this correctly?#2020-12-0920:39lreadSo I’m looking at my handy reference https://clojure.atlassian.net/browse/CLJ-1910#2020-12-0920:40borkdude> A keyword or symbol key without a namespace is read with the default namespace as its namespace.#2020-12-0920:41lreadhmm… I think I missed that “symbol key” detail…#2020-12-0920:42lreadso no, rewrite-cljc namespaced element support WIP does not handle this correctly yet!#2020-12-0920:42borkdudeIn clj-kondo this is a small fix:
user=> (keys (n/sexpr (p/parse-string "#:foo{x 1}")))
(foo/x)
#2020-12-0920:43borkdude
modified   parser/clj_kondo/impl/rewrite_clj/node/seq.clj
@@ -56,9 +56,11 @@
           m (first (node/sexprs children))
           nspace (name nspace-k)]
       (->> (for [[k v] m
-                 :let [k' (cond (not (keyword? k)) k
+                 :let [k' (cond (not (ident? k)) k
                                 (namespace k)      k
-                                :else (keyword nspace (name k)))]]
+                                :else (if (keyword? k)
+                                        (keyword nspace (name k))
+                                        (symbol nspace (name k))))]]
#2020-12-0920:43lreadoh foo! simple_smile …but am happy to realize this fact!#2020-12-0920:45lreadCLJ-1910 does deliver the gritty details, it just needs to be absorbed.#2020-12-0922:30borkdude@seancorfield Pushed a fix for https://github.com/borkdude/clj-kondo/issues/1093 to master. Re-scheduled the release for coming weekend.#2020-12-0922:38seancorfieldNice! Thank you, sir!#2020-12-1001:53Lone RangerHello Mr. @borkdude ! @sogaiu was kind enough to setup hooks for clj-kondo for #libpython-clj . We were having a discussion for template management via @seancorfield ‘s clj-new if it made sense to provide the clj-konda hooks with the template or if was better to let users setup and maintain their own clj-kondo hooks. The reason being, if something changes with libpython-clj in the future that would require a change in the clj-kondo definitions, I’m not sure it would be easy for us to distribute the new definitions along with the newer version. Have you encountered this problem before?#2020-12-1001:53Lone Rangerhttps://github.com/clj-python/clj-template/pull/9#issuecomment-742166487#2020-12-1010:31tomd:unsorted-required-namespaces appears to struggle with nested requires like so:
(ns foo
  (:require [charlie :as c]
            [delta
             [alpha :as a]
             [bravo :as b]]
            [echo :as e]))
alpha is marked as an unsorted namespace, which isn't really true, because the above is just a shorthand for:
(ns foo
  (:require [charlie :as c]
            [delta.alpha :as a]
            [delta.bravo :as b]
            [echo :as e]))
which isn't marked as unsorted. worth a bug issue?
#2020-12-1010:32borkdudeseems like a bug. issue welcome#2020-12-1010:41tomdhttps://github.com/borkdude/clj-kondo/issues/1097#2020-12-1010:45borkdudeThanks#2020-12-1010:34borkdudeMeanwhile you can ignore this using:
(ns foo
  #_{:clj-kondo/ignore [:unsorted-required-namespaces]}
  (:require [charlie :as c]
            [delta
             [alpha :as a]
             [bravo :as b]]
            [echo :as e]))
#2020-12-1010:34borkdude@helios Is this something you would like to look at since you wrote the original code?#2020-12-1010:47heliosno, sorry. don't have the time right now 🙂#2020-12-1110:21fmnoiseHi everyone, small question: using both kondo and joker in emacs currently, but thinking about getting rid of joker. Is kondo a full replacement currently or still better to keep 2 linters?#2020-12-1110:23borkdudeI have been running joker alongside clj-kondo (since I started with joker and then was inspired to build clj-kondo) and I think it would be safe to say that clj-kondo covers 99% of joker and offers a ton more linters. There might be very minor things like (let []) (warn on empty body in let) that are not in clj-kondo due to nobody asking for it but those are easy to add.#2020-12-1110:24fmnoisethanks a lot @borkdude!#2020-12-1117:13lreadNaive question: Is the fact that a dissoc on a record’s field returns a map instead of a record lint-worthy? Or is this something folks do normally and intentionally?
(defrecord MyRecord [field1 field2])
(def r (->MyRecord "22" "23"))
(dissoc r :not-a-field)
;; => #user.MyRecord{:field1 "22", :field2 "23"}
(dissoc r :field1)
;; => {:field2 "23"}
#2020-12-1117:24dominicm@lee detectign the type seems hard 99% of the time#2020-12-1117:24dominicmAlthough it'd be useful in the "this" case of a record#2020-12-1117:26borkdude@lee What lint warning would you expect in which example?#2020-12-1117:28lreadI was thinking the second dissoc might warn “a dissoc on a record returns a map”#2020-12-1117:29lreadI was not thinking of a warning on the first dissoc... was just trying to show a record was returned in that case.#2020-12-1117:31lreadbut maybe wanting to convert a record to a map in this way is a normal thing? I am too naive to know. 🙂#2020-12-1117:35dominicmIt's not often what you intend.#2020-12-1117:39lreadGood to know, @dominicm, thanks, (dec lread-naiveness)#2020-12-1117:41dominicmMost common bug of this kind I see is:
(defrecord DBComponent [conn-opts db]
  component/Lifecycle
  (start [this] …)
  (stop [this] (dissoc this :db)))
#2020-12-1117:41dominicmI don't remember if it matters in that exact position, but I think it's warned about.#2020-12-1118:22borkdudeMaybe this is more a case for clojure.spec since for clj-kondo it's not impossible but hard to know what dissoc on something is going to return and if this is or is not intended.#2020-12-1118:24borkdudeBut I'll keep it in mind#2020-12-1118:35lreadCoolio! Thanks @borkdude.#2020-12-1212:28borkdudeClj-kondo v2020.12.12 New: docs of all available linters! https://github.com/borkdude/clj-kondo/blob/master/doc/linters.md and 12 other fixed issues. Release notes: https://github.com/borkdude/clj-kondo/blob/master/CHANGELOG.md#v20201212 Special thanks to Clojurists Together for being the main sponsor in 2020Q4. Happy linting!#2020-12-1410:57Karol WójcikIs it possible to not show specific warning of custom macro? For instance I got the macro like
(defmacro in-node
  [& body]
  `(when config.core/NODEJS?
     
which is lint-as in config.edn in the following manner:
core.isomorphic/in-node      clojure.core/do
I would like this macro to not dispatch warning about redundant do.
#2020-12-1411:01borkdudeMaybe :lint-as clojure.core/when works? (lucky guess)#2020-12-1411:05borkdudeor clojure.core/fn maybe, something which receives a body but which is not do ;)#2020-12-1411:07juhoteperiI kind of remember looking at this, but maybe I confuse this with lint-as clojure.core/for giving "redundant let" warnings. But kind of same thing maybe?#2020-12-1411:09juhoteperiI think analyze-let-like-bindings has some additional checks to differentiate calls to clojure.core macros and lint-as macros? https://github.com/borkdude/clj-kondo/commit/3e138713b6183f7faca74af8f0aa2b1b0486a1ac#2020-12-1411:10borkdudetrue, we could do the same for do if that isn't the case already. An alternative would be to write a small hook. Redundant let + do is ignored from generated hook code#2020-12-1411:13Karol WójcikAlthough all proposals. Altough those remove the redundant do warning they introduce new ones.#2020-12-1411:14juhoteperiNot sure how to reproduce this, simple case seems to work:
❯ clj-kondo -c '{:lint-as {user/foo clojure.core/do}}' --lint -
(ns user)

(defmacro foo [& body] (when 2 
#2020-12-1411:15borkdude@juhoteperi You should use --config#2020-12-1411:16juhoteperiOops, also forgot backtick from the macro.
❯ clj-kondo --config '{:lint-as {user/foo clojure.core/do}}' --lint -
(ns user)

(defmacro foo [& body] `(when 2 
#2020-12-1411:17borkdude@karol.wojcik Why do you need :lint-as at all? If you just pass a body to that macro, I don't think you would get false positives? (it could very well be, I'm not awake enough yet)#2020-12-1411:19Karol Wójcik@borkdude you are right 😄 Thank you so much guys @juhoteperi @borkdude#2020-12-1505:21Sam StowersHey! Beginner here with a possibly dumb question. Trying to get clj-kondo going in emacs, but flycheck says the executable isn't found. Have already checked that clj-kondo is present in the emacs path etc - any thoughts on how I might get it working? Here's what M-x flycheck-verify-setup says:
Syntax checkers for buffer core.clj in clojure-mode:

  clj-kondo-edn
    - may enable: Automatically disabled!
    - predicate:  nil
    - executable: Not found

  clj-kondo-clj
    - may enable: Automatically disabled!
    - predicate:  t
    - executable: Not found

Flycheck Mode is disabled.  Use C-u M-x flycheck-disable-checker to
enable disabled checkers.

--------------------

Flycheck version: 31
Emacs version:    28.0.50
System:           x86_64-pc-linux-gnu
Window system:    x
#2020-12-1505:25sogaiupossibly this might help: https://gist.github.com/sogaiu/5f93faa7cab1d08a1510d281cadb0b81#2020-12-1505:27Sam StowersTried this, didn't work unfortunately. Just says the checker doesn't exist, or no selected checker#2020-12-1505:27Sam StowersOr "no syntax checkers disabled in this buffer"#2020-12-1505:29Sam StowersInterestingly, if I M-x flycheck-disable-checker on clj-kondo-clj, it then shows up in the C-u M-x command, but I still can't enable it from there.#2020-12-1505:33Sam StowersMy apologies if I'm missing something obvious - I'm learning both Emacs and Clojure at the moment#2020-12-1505:54sogaiui noticed you mentioned that clj-kondo is in the emacs path. would you mind elaborating on that point? i am not sure i understood it.#2020-12-1505:55sogaiumay be you were alluding to the somewhat common issue that occurs when emacs is started not from a terminal but from some kind of launcher or other means that doesn't happen to have an appropriate value for PATH.#2020-12-1506:15Sam StowersThe installation docs mentioned an issue that could happen if the $PATH in Emacs was different from the $PATH in a regular terminal. But I checked and the paths seemed identical#2020-12-1506:17Sam Stowershttps://github.com/borkdude/flycheck-clj-kondo#clj-kondo-is-on-my-path-but-flycheck-still-says-its-disabled-m-x-flycheck-verify-setup#2020-12-1506:44sogaiuthanks for the clarfication. so you did the M-x shell thing followed by echo $PATH i guess are you able to invoke clj-kondo via the sort-of-terminal buffer associated with invoking M-x shell?#2020-12-1506:47Sam StowersYes and yes#2020-12-1507:03sogaiuso i'm revisting when i had what seemed like a similar issue before: https://clojurians-log.clojureverse.org/clj-kondo/2019-10-24 borkdude mentioned that doing M-x flycheck-compile might be useful -- i think it may give more detailed output.#2020-12-1507:10sogaiuoh, i see "Flycheck Mode is disabled" in your initial output. have you done M-x global-flycheck-mode and/or is there a (global-flycheck-mode) somewhere in your emacs initialization setup?#2020-12-1507:20sogaiui guess so as flycheck-verify-setup might otherwise not show up#2020-12-1507:35Sam StowersI haven't yet. Will try that after a good night's sleep lol. Thanks for your assistance#2020-12-1507:36sogaiuhope you rest well!#2020-12-1509:50tvaughanThis is the error you’ll see if you’re using flycheck over TRAMP, https://github.com/flycheck/flycheck/pull/1842, FYI #2020-12-1521:45Sam Stowers@U0P7ZBZCK Thanks for the reply, but I'm not working on a remote host, and I don't think I'm using TRAMP.#2020-12-1521:45Sam StowersI guess I could try using M-x flycheck-set-checker-executable, but I'm not sure how to find the relevant executables#2020-12-1521:45Sam Stowersflycheck-default-executable-find doesn't seem to be exposed to M-x#2020-12-1522:42sogaiure: finding the appropriate executable -- for clj-kondo it should just be the full path to the clj-kondo binary. if you want to try out flycheck-default-executable-find, the following may work: * M-: * (flycheck-default-executable-find "clj-kondo") * RET then proceed through the interaction#2020-12-1701:10Sam StowersTried calling executable-find, it says there's a Lisp error.#2020-12-1701:24Sam StowersUpdate: solved#2020-12-1520:49borkdudehttps://twitter.com/borkdude/status/1338905522846769155 🎉#2020-12-1520:50borkdude@sam694 I think I'm using this tool https://github.com/purcell/exec-path-from-shell#2020-12-1521:39Sam StowersThanks @U04V15CAJ, but my echo $PATH output is identical when run in a regular terminal and run in M-x shell, so I don't think this is my issue. Unless there are other environmental variables that could be affecting this#2020-12-1521:42borkdudeSo when you type clj-kondo in the shell it works?#2020-12-1521:42Sam StowersYep#2020-12-1610:17dakraIs the path correct if you M-x getenv -> "PATH"?#2020-12-1701:15Sam Stowers...no, actually, seems to be missing node - which could be why it's not finding clj-kondo since I installed it with Node. That's interesting, I had assumed M-x echo $PATH would show the Emacs path#2020-12-1701:17Sam StowersI'll try installing the tool @U04V15CAJ recommended, will see if that fixes the problem#2020-12-1701:18sogaiuhave you considered installing clj-kondo some other way?#2020-12-1701:18Sam Stowers@UG1C3AD5Z If this doesn't work will try that#2020-12-1701:23Sam StowersIt's working! Thanks for the assistance @UG1C3AD5Z @U04V15CAJ @UFAP0C8KU 🙂#2020-12-1701:24Sam StowersTurns out I had exec-path-from-shell already installed as part of the emacs starter template I was using, but it lacked a necessary line in init.el#2020-12-1701:24sogaiucongratulations!#2020-12-1701:24sogaiuso perhaps for the installed-via-node pathway, exec-path-from-shell is important#2020-12-1701:30sogaiuthanks for sharing the solution! fwiw, i also use some linux and i don't install from node, nor do i use exec-path-from-shell, so i was finding it quite curious.#2020-12-1712:23practicalli-johnIs clj-kondo able to pick up files with - in the name rather than _ ? So if I had test/practicalli/lintme-test.clj instead of test/practicalli/lintme_test.clj I would get a warning.#2020-12-1712:24borkdudeclj-kondo will lint any file you throw at it#2020-12-1712:25practicalli-johnbut it does not tell me I should have used an underscore. I assume this is out of scope#2020-12-1712:25borkdudeMaybe you're asking about this? https://github.com/borkdude/clj-kondo/issues/842#2020-12-1712:25borkdudeStill waiting for @pez's PR ;)#2020-12-1712:26borkdudeFeel free to "upvote" the issue with a thumbs up#2020-12-1712:26borkdude(this is Github's silly way to prioritize issues)#2020-12-1713:31pezHaha, never heard the “Yes, fits this project” signal. 😃#2020-12-1713:31pezNot that you didn’t send it. It was just lost somewhere in transit. Haha.#2020-12-1713:53orestisSo I’ve put better-cond in my codebase… and clj-kondo can’t read it (obviously). I started implementing a hook for it but it’s tricky. @borkdude I remember you used it as an example but I’m quite lost since the discussions were using a different syntax.#2020-12-1713:55borkdude@orestis I have a test hook for better-cond: https://github.com/borkdude/clj-kondo/blob/master/corpus/.clj-kondo/hooks/better_cond.clj#2020-12-1713:55borkdudewhich I used to test-drive the hook functionality. But I'm not sure how complete it is#2020-12-1713:55borkdudeFeel free to add it to https://github.com/clj-kondo/config#2020-12-1714:10orestisIt’s not complete, but it’s a good starting point. I’ll bother you with some things if I don’t manage to finish it 🙂#2020-12-1715:30orestisDo you have a way to easily debug the various expressions? I’m trying to call api/sexpr but it seems to only work on the top level and I’d like to avoid writing the recursive version 😛#2020-12-1715:31borkdude@orestis Just call prn or println on the node#2020-12-1715:34orestisI get [<token: do> <list: (whena(dob))>] (no spacing)#2020-12-1715:34orestiswhich I think means:
(do (when a (do b))) 
but I’m not sure
#2020-12-1715:34borkdudethis is usually a sign that you garbled something#2020-12-1715:34orestisah good to know 🙂#2020-12-1715:35borkdudeit seems you have a vector of nodes and not a node object itself#2020-12-1715:35orestisIsn’t that common though? When you are taking the children of a node and want to do stuff?#2020-12-1715:35borkdudethis happens to me too, just keep printing and iterating ;)#2020-12-1715:36borkdudeyes, but you should put the children back into some node: (api/vector-node children) and not [children] in order for it to be a valid node#2020-12-1715:38orestisAh right, I was trying to figure out if it should be a vector-node or a list-node or what?#2020-12-1716:10orestisI’m getting the hang of this:
(defn process-pairs [pairs]
  (loop [[[lhs rhs :as pair] & pairs] pairs
         new-body [(api/token-node 'do)]]
    (if pair
      (let [lhs-sexpr (api/sexpr lhs)]
        (clojure.core/cond
          ;; single trailing element, flush the body
          (= 1 (count pair))
          (api/list-node (conj new-body lhs))

          ;; when node, recurse
          (#{:when 'when} lhs-sexpr)
          (api/list-node 
            (conj new-body (api/list-node
                             [(api/token-node 'when)
                              rhs
                              (process-pairs pairs)])))

          ;; let-like nodes
          (#{:let :when-let :when-some
             'let 'when-let 'when-some} lhs-sexpr)
          (api/list-node (conj new-body 
                               (api/list-node 
                                 [(api/token-node 'let)
                                  rhs 
                                  (process-pairs pairs)])))

          ;; normal conditions, just add them to the body
          :else
          (recur pairs
                 (conj new-body lhs rhs))))
      ;; no trailing element, flush the body
      (api/list-node new-body))))

(def cond
  (fn [{:keys [node]}]
    (let [expr (let [args (rest (:children node))
                     pairs (partition-all 2 args)]
                 (process-pairs pairs))]
      ;(println "COND" {:node (api/sexpr expr)})
      {:node (with-meta expr
               (meta node))})))
#2020-12-1716:12orestisThis deals with most cases — but not the “early bailing” ones (e.g. when-let) because the type-checking continues…#2020-12-1716:13borkdudeI bet better-cond would come in handy here ;)#2020-12-1716:13orestis
(b/cond
  :when-let [b nil]
  (+ 1 b))
#2020-12-1716:13orestisIn reality, (+ 1 b) is never evaluated because b is nil, but clj-kondo flags: expected number, got nil#2020-12-1716:13borkdudeah, that gives a false positive?#2020-12-1716:14borkdudewho uses nil in when-let though?#2020-12-1716:14borkdudethat's not a realistic use case#2020-12-1716:14orestisIt’s not too bad in practice since you never use explicit nils but doing the full thing would probably mean just lifting the implementation 1-1#2020-12-1716:14orestisGotta run 🙂 I’ll continnue this tomorrow.#2020-12-1716:14borkdude:thumbsup:#2020-12-1723:41Oliver GeorgeIdle thought: do you imagine clj-kondo might grow to include a --autofix flag to make the obvious corrections (e.g. remove redundant lets, remove unused bindings, convert if to when...)#2020-12-1809:01dominicmThat's been suggested as a external tool that takes the output, as to not bloat the main binary.#2020-12-1809:26borkdudeCarve is one of the tools that does rewriting based on clj-kondo output: https://github.com/borkdude/carve#2020-12-1809:26borkdudeif -> when is a simple transformation, but there are many that aren't so obvious#2020-12-1809:31Oliver GeorgeCarve is super handy.#2020-12-1810:52tvaughanKibit might provide some inspiration, https://github.com/jonase/kibit#2020-12-1810:56borkdudeIt's not so much a matter that it's not possible, it's just not something I find very important. The scope of clj-kondo is already big enough to spend time on existing issues in the backlog.#2020-12-1810:57borkdudeTools like clojure-lsp may pick up on clj-kondo's output and do it as part of the editor functionality for example#2020-12-1811:00tvaughanAs a flycheck user myself, it would be nice if I could train it to solve common errors in a way I specify #2020-12-1811:02borkdudeI've seen people write elisp based on the flycheck output#2020-12-1810:58borkdudeI might change my mind on this in the future, but right now it's not on the radar.#2020-12-1814:59dominicmhttps://github.com/neomake/neomake/pull/2516 will update clj-kondo docs following this being merged. :)#2020-12-1815:00borkdudewhat's this?#2020-12-1815:15dominicmVim linter, I'm adding upstream support.#2020-12-1815:17borkdudecool!#2020-12-1817:24dominicm(tired of having the config in my files)#2020-12-1818:22Eugenhi, I just saw this:
npm audit
npm ERR! code ELOCKVERIFY
npm ERR! Errors were found in your package-lock.json, run  npm install  to fix them.
npm ERR!     Invalid: lock file's 
#2020-12-1818:39borkdude@eugen.stan I'm not sure what this is. I don't maintain the npm package, but you could try post an issue at https://github.com/filipesilva/clj-kondo. He will probably suggest that you upgrade it#2020-12-1818:40Eugenthanks, will contact him. is the output of npm audit. Running npx npm-check-updates shows I am up to date#2020-12-1818:43EugenI did upgrade just now and everything is ok, strange that the update was not visible with the npm-check-updates#2020-12-1818:43Eugenthanks again#2020-12-1822:47borkdudeIf you are using the VSCode plugin, consider leaving a review: https://marketplace.visualstudio.com/items?itemName=borkdude.clj-kondo It's been downloaded 30k+ times but it has only 3 reviews :)#2020-12-1910:12Eugendone#2020-12-1910:19borkdudeThanks!#2020-12-2110:05borkdudeNeomake now has built-in support for clj-kondo: https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#neomake Thanks @dominicm#2020-12-2213:06borkdude@juhoteperi Congrats on the Reagent release 1.0.0! I notice for React functions you use :f> to call them. From a static analysis perspective, it would be nice to support an optional keyword in the first position of a normal component call as well, so e.g. clj-kondo could give you arity or type warnings. E.g.: [:r> my-component 1 2 3]#2020-12-2213:08borkdude(not sure about :r>, maybe something nicer like [:fn my-component 1 2 3] could also work)#2020-12-2213:09juhoteperi:r> is already used, it is for "raw" React components 🙂#2020-12-2213:09borkdude[::r/f component 1 2 3] aliasing reagent.core?#2020-12-2213:10borkdudemaybe too verbose. but something to think about. if this can be detected uniquely by clj-kondo, it would solve an open issue I've been thinking about for a long time#2020-12-2213:11borkdudeThe issue is here: https://github.com/borkdude/clj-kondo/issues/25#2020-12-2213:11juhoteperiI guess it would be OK to have keyword for the normal Reagent component also. Not sure how safe it would be to detect these keywords. Someone else could also be using them inside Hiccup vectors.#2020-12-2213:11borkdudeyeah#2020-12-2213:11juhoteperiBest would be if Reagent just had DOM functions like Helix (or Om...)#2020-12-2213:12borkdudeyou mean a function notation instead of vector?#2020-12-2213:13juhoteperiYeah
#2020-12-2213:13borkdudethen it would work automatically with clj-kondo.#2020-12-2213:14juhoteperiHelix uses macro to generate fns so that probably doesn't work without additional config: https://github.com/lilactown/helix/blob/master/src/helix/dom.cljc#2020-12-2213:16juhoteperiThough Helix components are used thorugh helix.core/$ macro so at they are easy to find... Anyway, I'll open issue on Reagent to keep track of ideas on making the forms easier to analyse.#2020-12-2213:19borkdudemaybe a simple solution would be to use a macro in reagent.core:
(defmacro f [& args] `[
so you can write:
(r/f component  1 2 3)
and this would uniquely signal a reagent component being called.
#2020-12-2314:58lreadDang @borkdude, every now and then, after clj-kondo instantly tells me I’ve got something wrong, I sit back and marvel at how helpful it is. What an awesome feedback loop!#2020-12-2314:58borkdudeEven though I have created it mostly myself, I can't help getting the same feeling from time to time, haha#2020-12-2315:01lreadWell, I think being a proud papa is in order here!#2020-12-2315:03lreadREPL driven development with an awesome linter is big silly grin inducing!#2020-12-2318:20seancorfieldI'll +100 that. I've gotten so used to clj-kondo spotting mistakes that sort take for granted that it's there: I just sort of expect my "editor" to point stuff out now and when I have to work on non-Clojure code it's so frustrating that stupid mistakes don't show up immediately! 🙂#2020-12-2319:04lreadI like that clj-kondo is not judgmental of the number of stupid mistakes I make. It just gently says, “hey buddy, you might not want to do that”.#2020-12-2416:48dominicmI'm currently working on a fork which remembers your failures and tweets them to make you feel bad.#2020-12-2420:06lreadHa! Don’t forget to make them extra mean tweets!#2020-12-2319:50nateMe too, clj-kondo is a great tool, grateful for it every day. Particularly grateful that it supports babashka.process's $ macro as I'm using that a lot these days.#2020-12-2416:48dominicmI'm currently working on a fork which remembers your failures and tweets them to make you feel bad.#2021-01-0214:30borkdudeAnnouncing the carve CLI: https://github.com/borkdude/carve#cli Carve is a tool to remove unused vars from your project, based on clj-kondo. Have fun!#2021-01-0509:51levitanongHallo! I'm playing around with the :hooks feature of clj-kondo, and I'd like to use clojure spec to use s/cat to easily parse the macro form, but SCI says it couldn't find clojure spec. Is there some extra step I need to take to get spec in there, or is it simply unsupported by SCI?#2021-01-0509:56borkdudeclojure spec isn't currently supported in clj-kondo hooks#2021-01-0510:42levitanongGot it, thanks#2021-01-0510:24borkdudeWould adding a .gitignore file automatically in the .clj-kondo directory be a bad idea? To ignore the .cache: https://github.com/clj-kondo/clj-kondo/issues/1113#2021-01-0510:26borkdude@levitanong Note that spec is still alpha, so even if I would add spec, I would not be comfortable with adding spec1 or spec2 in this stage. Another issue is that hooks usually return transformed nodes. Spec would probably only be useful for generating warnings based on the sexprs, not transformation, but maybe it can be used in that way too, not sure.#2021-01-0510:45levitanongAh, my intent is to make a hook for ghostwheel's >defn, which is basically just defn with something extra. Manually manipulating the form is quite a hassle since defn can take many forms, but s/conform can make it manageable with s/cat and stuff like s/? and s/*. But, it's not supported, so c'est la vie! I will manage 🙂#2021-01-0510:46borkdude@levitanong Maybe you can look at the hook for rum, which is quite similar: https://github.com/clj-kondo/config/blob/94da3d73ca0ced8f7f29c45a9283252d9e05ea57/resources/clj-kondo.exports/clj-kondo/rum/clj_kondo/rum.clj#2021-01-0510:47borkdudeAlso feel welcome to contribute your hook back to the config repo#2021-01-0510:54levitanongThanks for the tip! Another question: Where is hooks-api defined? I can't find it so far in the repository. 😮#2021-01-0510:55levitanongre: contrib, i'll do my best!#2021-01-0510:57borkdudeThe API is documented here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#api The code is here: https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/hooks.clj But note that anything that is not documented, should be considered implementation detail and might change or be removed.#2021-01-0510:58levitanongI was looking at that clj file, but it didn't match the require statement, so I assumed it was somewhere else 😮 Is some other process involved in exposing this file as a different namespace on execution?#2021-01-0510:59borkdude@levitanong Yes, the hooks are interpreted using sci: https://github.com/borkdude/sci#2021-01-0510:59levitanongOh okay, I get it now! I see the sci/init call#2021-01-0510:59levitanongThanks! I think this is enough for me to get going.#2021-01-0517:06levitanongI just realized there isn't much point in making a hook for ghostwheel because >defn is actually compatible with defn. so I can just use lint-as. I originally also wanted to use spec to use spec to immediately validate the form (i.e. making ghostwheel do its job statically) but that's not possible, so 🤷 😂#2021-01-0517:07levitanongit's a good learning experience though!#2021-01-0517:08borkdudeCool :)#2021-01-0517:09borkdude@levitanong You might be interested in this: https://github.com/clj-kondo/inspector#2021-01-0517:09borkdudeIt's a bit experimental, but if you want to play with it#2021-01-0517:17levitanongGoing through the readme, pretty cool! Is it compatible with clojurescript though? tried it of the cuff, but i'm getting a required namespace not available error, even after adding "configs/inspector" to my :config-paths#2021-01-0517:18borkdude@levitanong hmm, no, it currently only works on the JVM, but I think a .cljs version could be made#2021-01-0517:19borkdudeas long as it spits out the correct data#2021-01-0517:19levitanongah, alas. I'm currently working on a cljs project right now. I do have a clj project that i'll work on over the weekend, so i'll definitely try inspector on that!#2021-01-0510:42levitanongGot it, thanks#2021-01-0812:39delaguardoI found a “problem” with defmethod because defmethod expects & fn-tail it is possible to set local binding for the function that implement that particular method. but clj-kondo give me an error for such case#2021-01-0812:44borkdude@delaguardo Can you post this code as text instead of screenshot?#2021-01-0812:45delaguardo
(require '[clojure.string :as string])

(defmulti example :tag)

(defmethod example :node
  f
  ([] "NODE: ")
  ([{:keys [children]}]
   (str (f) (string/join " " (map example children)))))

(defmethod example :leaf
  f
  ([] "LEAF: ")
  ([{:keys [value]}]
   (str (f) value)))
sure
#2021-01-0812:47delaguardothis is definitely an edge case which I never saw in real examples so I came here to check if this is something that should be addressed in clj-kondo.#2021-01-0812:48borkdudeah, so multimethods fns can be named. didn't know that So a working example would be:
(prn
 (example {:tag :node :children [{:tag :leaf :value 1}]}))
#2021-01-0812:48borkdudeit also works with bb :)
$ bb /tmp/mm.clj
"NODE: LEAF: 1"
#2021-01-0812:49borkdudeFeel free to make an issue about this#2021-01-0812:54borkdudeyou can ignore the false positive with #_:clj-kondo/ignore (f)#2021-01-0813:04delaguardohttps://github.com/clj-kondo/clj-kondo/issues/1115#2021-01-0813:04borkdude:thumbsup:#2021-01-1401:18didibusSo, @seancorfield made me realize that if you change the arity of a fn in one namespace, and use it with the wrong arity in another namespace clj-kondo will catch the error. But, if the fn is deleted from the other namespace, or renamed, it won't catch those. Is that normal? Would it be possible for clj-kondo to warn on those as well? It seems to me if it can track the arity, it must also track what var is defined in each namespace no ?#2021-01-1408:22borkdudeWork in progress. I worked on this issue but it requires more work. It is something that I want to support eventually though.#2021-01-1419:22didibusSo I assume there is already an issue for it and I shouldn't create one?#2021-01-1419:35borkdudeThis is the issue: https://github.com/clj-kondo/clj-kondo/issues/634#2021-01-1415:53Aleksander RendtslevHi, This might be a naive question, but I haven’t been able to figure it out: How do I import library provided configs? Eg. Pathom comes with a .clj-kondo/config.edn, but my editor doesn’t pick it up. The guide of the config repo worked fine. So I got it to work for rum/fulcro etc. But I can’t figure out how to do it for everything outside of that (I’m still pretty new to Clojure so this is probably a rookie mistake)#2021-01-1415:57borkdude@aleksander990 There is a difference between a config that a project itself uses and the config that is needed for consuming the code of that project.#2021-01-1416:15Aleksander Rendtslevyeah, I think I got that part. Eg: Adding the fulcro config to .clj-kondo/config/fulcro/config.edn (by following the instructions in the config repo) and then adding that to config-paths in my own config.edn. I just can’t figure out how to do the same for pathom (outside of simply copy pasting the config from their repo) No worries. clj-kondo feels like a lifesaver and is absolutely great for beginners. So I figured my ignorance might be of some help#2021-01-1416:15Aleksander RendtslevI did read through the guide below, but still can’t wrap my head around it#2021-01-1415:58borkdudeYou can read more about this here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration I'm going into a meeting now, but I'd be happy to answer more questions later.#2021-01-1416:18Aleksander RendtslevSounds good. Thank you for being so responsive!#2021-01-1416:57borkdudeok, I'm back.#2021-01-1417:08Aleksander RendtslevSo my question is: How do I add an external libraries configuration to my linter? (in this particular case pathom) https://github.com/wilkerlucio/pathom I followed this guide to add the ones provided in this repo, and I figured I just have to tweak the approach for pathom? https://github.com/clj-kondo/config I just haven’t been able to figure out how#2021-01-1417:16borkdudeSo what pathom should do in this case is export the config for its library in a clj-kondo.exports directory that will be part of the library artifact#2021-01-1417:16borkdudeand preferable it should only export config for itself, not for other libraries (like fulcro, because fulcro is not part of pathom)#2021-01-1417:17borkdudeBut for now you could also copy this config to clj-kondo/config, if pathom isn't doing this in the foreseeable future. Or just copy the relevant bits to your own config.edn file.#2021-01-1417:17borkdude@U066U8JQJ ^#2021-01-1417:34Aleksander RendtslevOk, so it’s the clj-kondo.export part that’s missing. That makes sense. Thanks! I’ll copy it over for now#2021-01-1417:36wilkerluciocool, sounds nice, I'll take a time to check on it later today 👍#2021-01-1418:16wilkerlucio@U04V15CAJ looks right? https://github.com/wilkerlucio/pathom/pull/186#2021-01-1418:48borkdude@U066U8JQJ Looks right to me!#2021-01-1419:05wilkerluciocool, does this works with deps dependencies too?#2021-01-1419:51borkdudeit works with whatever build tool, as long as its on the classpath#2021-01-1419:52borkdudeSo anyone who has pathom on their classpath, should get a hint about the config with:
clj-kondo --no-warnings --lint "$(clojure -Spath -Sdeps)"
#2021-01-1419:56wilkerlucioI was playing with it here#2021-01-1419:57wilkerlucioI updated my async library to provide those#2021-01-1419:57wilkerlucioand then add as a dep, when I used the clj-kondo --no-warnings --lint "$(clojure -Spath -A:provided)" --parallel, it copied the file, as expected#2021-01-1419:58wilkerluciobut, if I get the same library, and add it via deps (instead of the clojars), then when I run the lint, no copy happens#2021-01-1419:58wilkerlucioI guess because in the second case the clj-kondo.exports isn't at the root, but at resources instead#2021-01-1419:58borkdudeit depends on your deps.edn, does it have "resources" in its :paths ?#2021-01-1419:58wilkerluciogood point, let me check that#2021-01-1420:01wilkerluciothat was the missing bit! now that resources in the classpath its working 👍 thanks!#2021-01-1420:02wilkerlucioshould a library commit those loaded external kondo configs, or leave ignored in the repo?#2021-01-1420:02borkdudeI think it's good to commit so anyone working on that project gets it automatically#2021-01-1420:03wilkerluciomakes sense#2021-01-1420:33wilkerlucio@aleksander990 released in pathom 2.3.1#2021-01-1422:48Aleksander RendtslevAmazing! Thank you @U066U8JQJ#2021-01-1422:49borkdude🙏#2021-01-1419:26didibusCan you teach clj-kondo to recognize data_readers ?#2021-01-1419:34borkdude@didibus I don't think there is any logic for that yet.#2021-01-1419:34borkdudeFeel free to create an issue#2021-01-1509:36dominicmWe're starting to mark some code as deprecated, and I didn't see any kondo tests for deprecated namespaces. Clojure has hinted at supporting this: https://clojure.atlassian.net/browse/CLJ-706? I'm guessing kondo doesn't by lack of tests.#2021-01-1509:37borkdudeclj-kondo does lint deprecated vars, but not deprecated nss. Feel free to create an issue#2021-01-1509:37dominicmCool :).#2021-01-1509:38borkdudeoh, I see there is no clear standard for this yet?#2021-01-1509:39dominicmI think there's a clear standard, just no clear impl in clojure itself yet.#2021-01-1509:39borkdudeI guess detecting :deprecated true or :deprecated "1.10.1" in the metadata of the ns is sufficient#2021-01-1509:39dominicmYup#2021-01-1509:43dominicmCool, opened :)#2021-01-1509:44borkdude> A warning similar to the one when using a deprecated namespace you mean var right?#2021-01-1514:10delaguardo
❯ echo '(defn- foo [x] (when x (foo false)))' | clj-kondo --lint -
linting took 14ms, errors: 0, warnings: 0
this might be a little bit odd false-positive linting result private foo is not used anywhere except in foo’s body compare with that
❯ echo '(defn- foo [x] (when x 1))' | clj-kondo --lint -
<stdin>:1:8: warning: Unused private var user/foo
linting took 11ms, errors: 0, warnings: 1
is it worth to file an issue?
#2021-01-1514:22borkdudeyeah, I think that warrants an issue. I think carve already handles this correctly#2021-01-1613:03martinklepschI’d like a fuzzy var finder in my editor and I like the idea of using clj-kondo for it since it doesn’t require a REPL connection etc. How would I go about getting that metadata from clj-kondo?#2021-01-1613:05borkdude@martinklepsch This page should get you going: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#2021-01-1613:06borkdude@martinklepsch An example script I've built recently with bb + clj-kondo to get an API diff: https://gist.github.com/borkdude/ba372c8cee311e31020b04063d88e1be#2021-01-1616:55clyfeVia calva > lsp > kondo (I think..): > Unused declaration: foo clojure-lsp(unused-public) Tried: #_{:clj-kondo/ignore [:unused-public]} but that does not ignore.#2021-01-1616:56borkdude@claudius.nicolae The issue in that channel is that the warning is coming from clojure-lsp, not from clj-kondo itself#2021-01-1616:56borkdudeSo it's not a clj-kondo issue#2021-01-1715:56nivekuilclj-kondo flags this: (set/difference #{:a :b} (keys {:a 1})) but it actually does work. That seq from keys can be used like a set#2021-01-1716:24borkdude@kevin842 this is undeterministic behavior.
(instance? java.util.Set (keys {:a 1}))
false
E.g. this will crash:
user=> (set/difference #{:a :b} (keys {:a 1 :b 2 :c 3}))
Execution error (IllegalArgumentException) at user/eval7 (REPL:1).
contains? not supported on type: clojure.lang.APersistentMap$KeySeq
#2021-01-1717:01nivekuiloh, interesting! I wonder why that is the case.. isn't it just a view over the actual collection, which it knows to support o(1) access?#2021-01-1717:07nivekuilI must be thinking of python, where dict.keys() does return a set-like view:
>>> "b" in {"a": 1, "b": 2}.keys() True
in any case not relevant to this channel :)
#2021-01-1717:07borkdude@kevin842 this happens because set/difference checks which input is larger and uses that to make things faster#2021-01-1717:07borkdudesame for union, etc#2021-01-1717:08borkdudeso never use those fns with something else than sets#2021-01-1816:42ericdalloHey @borkdude, I just noticed the :unused-namespace type from :findings in clj-kondo don't contain which namespace is unused, am I missing something?#2021-01-1816:43ericdallofor example a code like this:
(ns foo.bar (:require [bar :as b]))
Gives me the finding:
{:type :unused-namespace,
  :message "namespace bar is required but never used",
  :level :warning,
  :row 1,
  :end-row 1,
  :end-col 21,
  :col 18,
  :filename "/a.clj"}
#2021-01-1816:44ericdalloit'd be nice to have a :ns bar#2021-01-1816:46borkdudeFindings generally don't have this information (since this is not output to linter editor integration in general) but I think we could add it, without breaking things :)#2021-01-1816:46borkdudePR welcome#2021-01-1816:47ericdallothanks 🙂 I don't know clj-kondo code, any tips on what/where change it? I'd love to help 🙂#2021-01-1816:48borkdudegrep for "is required but never used" and this should be relatively easy to plug in. Usually this is tested either in main_test.clj or unused_namespace_test.clj (or something like this). Grep should also show where this is tested#2021-01-1816:48ericdalloThank you! 👀#2021-01-1816:49borkdudehmm, but the tests round-trip from the text output, so a test calling the core namespace should be added separately to test for the :ns addition#2021-01-1816:49borkdudeLet me know if you have any questions#2021-01-1816:57ericdalloWhat do you think it's the best, merging https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/linters.clj#L405`node->line` with something like {:ns ns-sym} and {:refer :refer-sym} for unused-refer lint or adding a name or extra arg for node->line ?#2021-01-1816:58borkdude(assoc ... :ns ns-sym)#2021-01-1816:58borkdudemerge is best avoided, assoc is faster ;)#2021-01-1816:59ericdallonice!#2021-01-1817:15ericdalloAny reason why load the ns with cider fails because of missing deps me.raynes.conch ?#2021-01-1817:16borkdudeare you running with deps.edn?#2021-01-1817:16borkdudeYou should include the :test alias then#2021-01-1817:17borkdudesame for lein: with-profiles +test#2021-01-1817:33ericdalloI'm having a hard time to make cider use the test lein profile :man-facepalming: 😂#2021-01-1817:34borkdudeThis is why I never use cider-jack-in. I always use cider-connect#2021-01-1817:34borkdudeTo be honest, with clj-kondo development, I almost never use a REPL. I always just use the command line#2021-01-1817:36ericdalloI got it, but yeah, I agree that could work too#2021-01-1817:36ericdallomaybe in a near future when clojure-lsp uses clj-kondo 😜#2021-01-1817:37borkdude
clojure -M:clj-kondo --lint - <<< '(+ 1 2 3)' 
#2021-01-1817:55ericdallo@borkdude the tests on main_test don't return the added :ns , I think this is what you meant above right? how can I test that?#2021-01-1817:55ericdallosorry for too many questions 😅#2021-01-1818:00ericdalloThis is the draft atm https://github.com/clj-kondo/clj-kondo/pull/1132#2021-01-1818:43borkdude@UKFSJSM38 yeah, instead of (lint! ...) you just call (-> (with-in-str "your-code" (clj-kondo.core/run! {:lint ["-"]}) :findings)#2021-01-1818:43borkdudeso as an API call basically. lint! mimics the command line usage (the primary way in which clj-kondo was initially used)#2021-01-1818:44ericdalloGot it, should I add that as a new deftest in core_test or a new test ns?#2021-01-1818:44borkdudeI think you can put it along with the other unused-ns tests#2021-01-1818:44ericdallolike unused_namespace_test.clj#2021-01-1818:44ericdallook#2021-01-1818:45borkdudebut also feel free to move the existing ones to unused_namespace_test.clj if that doesn't exist yet#2021-01-1818:45borkdudemain_test is way too big#2021-01-1818:45ericdalloyes, I can do that 😄#2021-01-1819:40ericdalloDone @borkdude, thank you for the help during this 🙂 LMK if any issues with the PR: https://github.com/clj-kondo/clj-kondo/pull/1132#2021-01-1822:36borkdudeI merged a new linter called :unresolved-var to master now. It will give a warning on the following: (require '[clojure.set :as set]) (set/onion #{1 2 3}): "No such var: set/onion". The default level is :off but will be bumped to :error when this is done (there are 2 TODO items left). You can download a binary from the CircleCI builds if you would like to give this a spin in your daily dev (or use on the JVM). Testing is highly appreciated.#2021-01-1911:56dominicmI noticed that kondo doesn't warn when the same arity is repeated. Pretty minor as Clojure catches it.
(defn foo
  ([x] x)
  ([x] (inc x)))
#2021-01-1911:56borkdudeissue welcome!#2021-01-1918:18lreadHiya! Has anyone ever asked to warn on usage of prefix lists in namespaces? https://stuartsierra.com/2016/clojure-how-to-ns.html#prefix-lists#2021-01-1918:18borkdude@lee I think this will be part of the next release#2021-01-1918:18lreadAwesome!#2021-01-1918:19borkdude(already on master)#2021-01-1918:19borkdudeoh sorry, you mean, warn on usage of these things at all?#2021-01-1918:19lreadyeah#2021-01-1918:19borkdudethere are some lint warnings about invalid prefix lists#2021-01-1918:19borkduderecently added#2021-01-1918:19borkdudebut not the one you asked for#2021-01-1918:19lreadlike follow Stuart’s advice and avoid using them at all#2021-01-1918:25borkdudeyeah, feel free to add an issue. I think not using them is preferable#2021-01-1918:25lreadok, thanks, will do#2021-01-1918:40didibusI'd caution against clj-kondo becoming too much like CheckStyle#2021-01-1918:41didibusCatching mistakes and bugs are good, no one will ever complain. Forcing your opinions on a particular style are bad, and people will start to hold grudges and discontent against you 😛#2021-01-1918:41lreadYeah but they can be off by default.#2021-01-1918:41didibusFor style concerns, focus on automated-styling tools instead. Like a tool that automatically rewrites the ns declaration to your agreed team style#2021-01-1918:41lreadWe already have some style linters.#2021-01-1918:42lreadlike: missing else branch on if#2021-01-1918:43borkdude@didibus I don't agree. Clj-kondo checks many style things and almost all of them are disabled by default if they are controversial. This is one of the core things of clj-kondo and adding more makes sense, even if not all people use them.#2021-01-1918:44didibusI wouldn't call that a style linter. That can actually be a bug, and I've had it be a bug before where that warning helped me catch the fact my parenthesis were wrong so I was missing an else branch.#2021-01-1918:44didibusIf they are disabled by default its a lot better. That said, I would be worried of seeing a thing where like the default lein template drops a pre-configured clj-kondo config into a project with some forced def "style" linters turned on, etc.#2021-01-1918:45didibusI kinda just hope in my dreams that Clojure doesn't devolve to Java's shenanigans. And that for styling we'd focus efforts on re-formatting tools.#2021-01-1918:47didibusBut hey, I have CheckStyle PTSD, this is just my 2 cents.#2021-01-1918:49didibusLike a linter is defined as: > lint, or a linter, is a static code analysis tool used to flag programming errors, bugs, stylistic errors, and suspicious constructs And I think this is all good. The "stylistic error" part I guess is maybe the more controversial, but ya if those are off and can be customized I'll be happy. > Checkstyle is a static code analysis tool used in software development for checking if Java source code is compliant with specified coding rules This is bad bad in my opinion 😛#2021-01-1918:50borkdudeI get your point, don't worry. Most if not all of the opinionated things going into clj-kondo since a while has been disabled by default.#2021-01-1918:50didibusYa, I've been very happy with the choices you've made and have full confidence.#2021-01-1918:52didibusApology, I think my comment came off as more negative, I wanted to emphasize on the alternative more so than on shutting down the use of clj-kondo for style. Like a team can have their own conventions and I have no issue with that. But what is even more awesome than having something tell you you didn't do things the way the team wants them, is a tool that fixes it automatically for you.#2021-01-1918:52lreadYou’ll just be annoyed if submitting PRs to my projects because I’ll have all the linters on. (just teasing)#2021-01-1918:52borkdudeOne tool that fixes it automatically for you is clojure-lsp.#2021-01-1918:53borkdudeIt's using clj-kondo under the hood and will fix it using your editor integrations.#2021-01-1918:53borkdudeAnd there are other tools like carve which also do this.#2021-01-1918:53didibusYa, I think clj-kondo would be a great underlying lib to leverage for that#2021-01-1918:54borkdudeThe focus of clj-kondo is code analysis and linting (including style), but it won't provide rewriting#2021-01-1918:54borkdudeJust the output should be enough to write tools on top of this#2021-01-1918:54didibusTotally make sense.#2021-01-1918:54didibusThe custom analysis seem to be a good start for that.#2021-01-1918:55borkdudeThanks for test-driving the :unresolved-var linter.#2021-01-1918:56didibusThat said, there is one difference. If the linter is: warn on use of "bad style", it is not letting you choose your preferred style, it is making an opinionated choice on what style is good and bad. Like what if I prefer all my ns to be written the other way? (ns foo (:require [a.b c d e g]))#2021-01-1918:57lreadAs I write out the issue, I’m remembering that prefix lists are invalid in cljs. I’ll make a note in the issue.#2021-01-1918:58didibusAh, now that's a good observation 😛 See now you could almost argue it should be a warn by default, since its now in the category of possible error#2021-01-1918:59lreadI knew I’d win you over. simple_smile#2021-01-1918:59didibus😛#2021-01-1919:01didibusYa, I guess its just nuanced. @borkdude has had great instinct I think to put the line in the right place. CheckStyle on the other hand has not.#2021-01-1919:03didibusLike the missing-docstring linter being applied only to public var. Like that's a pretty good way to handle it. Where as in CheckStyle this is one of my most hated linters, but that's because it forces everything to have a docstring. So you'll see stupid things like:
// The customer id
private String customerId;
#2021-01-1919:06didibusAlso depends how you use it too. CheckStyle is slow to run, and can't be integrated in your editor (well it can but not in a way you get feedback as you type). So people always set it up as a build step or a PR approval step. Pretty frustrating to have it fail when you're ready to push because your private customerId field doesn't have a doc-string. But clj-kondo gives you instant feedback, so I think that helps a lot with frustration. And you could easily set it up to only fail on error, so warns can be a recommendation, like "Probably have a doc-string here, unless the doc-string is a copy/paste of the var name with The added in front 😛"#2021-01-1919:06lreadhttps://github.com/clj-kondo/clj-kondo/issues/1137, @didibus I was even so cheeky as to include your require example above as my code snippit.#2021-01-1919:10lread@didibus I sympathize with your PTSD from silly CheckStyle rules. I vaguely remember them too, but the memory for me is fading, and the healing is almost complete.#2021-01-1919:17didibusYa, CheckStyle has some stupid rules, especially when combined with Java, makes it really annoying. In Clojure, sometimes "style" enforcement is more like: Clojure is so loose, that you can't even remember what "style" is a bug and which one is not. Like using :else in cond. That linter is nice, not because it forces me to use :else and not :default, but because I actually never remember if I'm supposed to use some specific keyword or not.#2021-01-1919:19didibusAnd then you do get a lot of weird stylistic errors, like not knowing that I could easily think this makes sense:
(cond
  (pred? a)
  (foo a)
  :else
  (bar a)
  :default
  (baz a))
#2021-01-1919:21didibusBy the way, hum, is that a linter? Would be a good one to have: Unreachable cond branch. Or something like that#2021-01-1919:23borkdude@didibus
$ clj-kondo --lint /tmp/foo.clj
/tmp/foo.clj:2:4: error: Unresolved symbol: pred?
/tmp/foo.clj:2:10: error: Unresolved symbol: a
/tmp/foo.clj:3:4: error: Unresolved symbol: foo
/tmp/foo.clj:5:4: error: Unresolved symbol: bar
/tmp/foo.clj:6:3: warning: unreachable code
/tmp/foo.clj:6:3: warning: use :else as the catch-all test expression in cond
/tmp/foo.clj:7:4: error: Unresolved symbol: baz
linting took 130ms, errors: 5, warnings: 2
#2021-01-1919:24didibus> warning: unreachable code Nice!#2021-01-1919:26didibusI'm super excited for the unresolved var linter. Thanks so much for putting the work on it by the way!#2021-01-1919:27didibusA number1 complaint I see from people is always: Refactoring in Clojure is hard cause you can't tell what you broke. And so that linter I think is a huge step to help with that.#2021-01-1919:32borkdudeA few small items to fix and hopefully a release tomorrow or in the weekend... 🤞#2021-01-1919:34borkdudeone important thing: it should probably support a config to exclude certain vars or entire namespaces#2021-01-1919:34borkdudee.g. namespaces that have a lot of auto-generated vars using macros#2021-01-1919:35didibusYes, I was also wondering, would it work with hooks? Like if I have a hook for a macro that returns:
(do (defn foo ...)
   (def bar ...))
Will clj-kondo then know that this namespace contains a foo and a bar var?
#2021-01-1919:35borkdudeyes#2021-01-1919:36borkdudeat least, it should#2021-01-1919:37didibusCool, ya that's great then. I think most macros that generate vars do return a form close to that. So hopefully as more macros provide a hook, the number of vars/namespaces you need to exclude would get smaller.#2021-01-1919:38borkdudethere is also lint-as and clj-kondo.lint-as/def-catch-all, so in many cases no hook needed#2021-01-1919:38didibusOh ya, that's true#2021-01-1919:38didibusEven better#2021-01-1919:38borkdudebut it still takes effort to configure of course. I was thinking we could also have a runtime clj-kondo plugin that scans your project and emits cache info that can then be used by static analysis#2021-01-1919:39borkdudeso you would at least not get false positives for unresolved vars#2021-01-1919:41didibusHum... So like it would learn as the code is running? You could have a nRepl middleware maybe. And a way to set it up in your test-runner.#2021-01-1919:42didibusThough there's a disadvantage to that as well. Which is the same with the REPL, its possible that you defed something that you later deleted from the code.#2021-01-1919:42borkdudeyeah, I think you would run it only occassionally from the command line as a JVM CLI tool#2021-01-1919:43borkdudeto update the un-analyzable vars#2021-01-1919:43didibusI think if all it did was like load everything and let macros macro-expand. That would make sense.#2021-01-1919:44borkdudeyes, it would only load namespaces, then all-ns, ns-publics, and emit#2021-01-1919:45didibusYa that would be like automatic hooks. And it only wouldn't work if you're doing side effect, but in practice it would also work, cause you'd know that when running that, just like running your tests, you need to make sure you have the right environment setup.#2021-01-1919:45didibusIts a good idea#2021-01-1919:46borkdudea bit similar: https://github.com/clj-kondo/inspector#2021-01-1919:48didibusOh that's nice.#2021-01-1919:49didibusWhy does it need to be at runtime? When you call emit-types it walks the spec registry?#2021-01-1919:49borkdudeyes#2021-01-1919:50didibusYa, that's neat. I guess then this say runtime-analyze tool could do both: load namespaces, then all-ns, ns-publics, and emit cache and emit types.#2021-01-1919:52didibusFor specs though, in theory (and I get that its more work), can't you figure out what the specs are from the require and walking through the namespaces for calls to s/def and s/fdef ?#2021-01-1919:52didibusLike statically#2021-01-1919:53borkdudeSpecs are quite difficult to analyze accurately statically as they can have many indirections, although clj-kondo could do a best-effort attempt#2021-01-1919:54didibusHum, ya that's true. It does sound tricky since they can refer to others with namespace keys and all.#2021-01-1919:54borkdudeIt can be done, but a lot of work so that's why I went with the runtime approach, just as an experiment#2021-01-1919:54borkdudeMalli does a similar thing#2021-01-1919:55borkdudeSpec still being alpha, I don't want to build this into any tools yet#2021-01-1919:59didibusYa makes sense. I feel spec 2 is actively being worked on as well so.#2021-01-1919:46didibusI guess it only leaves this:
(ns foo)

(defn foo []
  (def f (fn [a b] (+ a b))))

(ns other (:require [foo :as foo]))

(foo/f 1 2)
As the edge case, where you would still need to use exclusion.
#2021-01-1919:52borkdudeWhy is that an edge case? This could be seen at runtime as well?#2021-01-1919:53didibusWell, in theory, every run of the program is not guaranteed to have the same defined vars#2021-01-1919:54borkdudeyou mean, if you conditionally define vars based on the weather?#2021-01-1919:56didibusHum... actually I think you are correct, I don't think this is even possible, cause the symbol passed to def has to be static.#2021-01-1919:57didibusLike you can't do:
(defn foo [username]
  (def username {}))
#2021-01-1919:58borkdudeyou can use intern to do this dynamically#2021-01-1919:58didibusI guess you could with a macro:
(defmacro create-user [username]
  `(def ~(symbol username) {}))
And then ya, I mean you'd need to exclude the linter on this namespace, cause you're getting dynamic usernames from the user at runtime and creating vars with them.
#2021-01-1919:58borkdude(if (< 20 degrees-fahrenheit) (intern 'foo.bar 'baz 1) (intern 'foo.baz 'bar 2))#2021-01-1919:59borkdudeeven with the macro, the input to the macro is static#2021-01-1919:59borkdudeI guess you could also use (eval ...)#2021-01-1920:00borkdudeso barring intern and eval, most of the var names can be statically known, and surely at runtime#2021-01-1920:00didibusOh ya, you're right. Ok, so only with intern could someone do this? Or is it just not possible?#2021-01-1920:00didibusYa, I mean, if you're doing eval or intern, you know what you are doing, and won't mind excluding your namespace I think.#2021-01-1920:01borkdudeor excluding only certain vars#2021-01-1920:02didibusWell, I mean, if you're doing a dynamic var def like I'm describing, you don't know what the vars will be because they are based on external input.#2021-01-1920:02borkdudehugsql is an example that comes to mind. but I know a nice trick for that: Have a dedicated foo.domain.hugsql namespace which is only dedicated to turning sql into vars, without any other fns. This namespace doesn't end up in your cache (because it has no statically analyzable vars) so it won't give you any errors in the unresolved-var linter.#2021-01-1920:03borkdudeI discovered this today at work ;)#2021-01-1920:03didibusOk ya, that is a good example#2021-01-1920:03didibusIf you had that runtime caching tool, it would be able to learn the vars generated from hugsql right?#2021-01-1920:04borkdudeyes#2021-01-1920:05didibusI think even a hook for hugsql could work here. If the hook is willing to do a "side-effect". In theory, the hugsql hook could be smart enough to say: "Warn can't find sql files". And if it can find them, to return the defs from it#2021-01-1920:05didibusUnless people often put their SQL definition in a DB or something like that, but I don't think so. They're generally a resource I think#2021-01-1920:06didibusAnyway, ya its a pretty good idea to have a runtime caching system. Seems it could cover a lot of those edge cases.#2021-01-1920:07didibusAnd still, I feel for all these edge cases, its not that big a deal to exclude the namespace or the vars from the unused-var linter.#2021-01-1920:11borkdudeyeah, it's kind of a last resort that should justify itself with enough frustration and so far the frustration hasn't been big enough yet ;)#2021-01-2012:58Felipe de MoraisIs there a config to make clj-kondo fix the issues instead of just raise it? 👀#2021-01-2013:04borkdude@felipejpa15 clj-kondo only outputs warnings or information that other tools can use to automatically fix the issues. clj-kondo itself will not rewrite your code#2021-01-2013:05borkdudeIf you are looking for refactoring tools, maybe try clojure-lsp or clj-refactor#2021-01-2015:12borkdudeAny preferences?
$ clojure -M:clj-kondo --lang clj --lint - <<< "(clojure.core/x)"
<stdin>:1:2: warning: No such var: clojure.core/x
This uses the same message as the clojure compiler would output, but the linter is called :unresolved-var. So the message could also be:
Unresolved var: clojure.core/x
#2021-01-2015:26borkdudeHmm, I think Unresolved var is better for consistency and also, clj-kondo might have a false positive in which case "No such var" would not be true, but "Unresolved var" would be ;)#2021-01-2019:17borkdudeClj-kondo v2021.01.20 New: unresolved var linter and various other improvements! See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-var for details. Release notes: https://github.com/borkdude/clj-kondo/blob/master/CHANGELOG.md#v20210120#2021-01-2019:20borkdude#2021-01-2121:38didibuswOOt WooT!!#2021-01-2108:47rickmoynihanWhat do people think of a clj-kondo linter that warns on aliased keyword usage? e.g.
(ns blah.blah (:require [foo.bar :as bar]))

::bar/baz ;; <- WARNING: aliased keyword 

:foo.bar/baz ;; <-- ok
i.e. to encourage find/replaceable keywords
#2021-01-2109:36rickmoynihanhttps://github.com/clj-kondo/clj-kondo/issues/1140#2021-01-2121:40didibusI think there's a linter that warns for inconssistent aliasing#2021-01-2121:41didibusNot sure if it cover keywords#2021-01-2121:41didibusBut if it did, you could use that to still make it easy to find/replace, and still let people use aliases#2021-01-2121:42didibusBasically, it forces the alias to be consistent across the board. So you know that you just need to find/replace that one alias.#2021-01-2108:50borkdude@rickmoynihan @snoe and @ericdallo and currently working on adding keyword analysis output (for LSP) but this would also allow you to get all aliased keywords (and write a tool that spits out warnings). But it can also included in clj-kondo pretty easily and by default turned off.#2021-01-2108:53rickmoynihancool… so clj-kondo currently doesn’t preserve that sort of data or have keyword analysis, that would make this linter easy?#2021-01-2108:54borkdudeyes, the information is there, there is just not such a linter right now#2021-01-2108:55rickmoynihancool#2021-01-2108:55rickmoynihanSimilarly I was thinking of another for integrant keys, that ensures the keys are compatible with ig/load-namespaces e.g.
(ns foo.bar (:require [integrant.core :as ig]))

(defmethod ig/init-key :wibble/wobble  ;; <-- WARNING: integrant key does not match the namespace defining  ig/init-key not discoverable by ig/load-namespaces
   [_ opts] ,,,) 

(defmethod ig/init-key :foo.bar/baz  ;; ok
   [_ opts] ,,,) 

(defmethod ig/init-key :foo/bar  ;; ok
   [_ opts] ,,,) 
#2021-01-2109:36rickmoynihanhttps://github.com/clj-kondo/clj-kondo/issues/1141#2021-01-2108:55borkdudewhat would make wibble/wobble not compatible?#2021-01-2108:56rickmoynihanthe defmethod would need to be put in a namespace wibble.wobble or wibble (single segment namespaces aside)#2021-01-2108:59rickmoynihanessentially ig/load-namespaces uses the key names specified in the integrant config to load the set of configured keys / namespaces. So it infers the namespace from the keywords name#2021-01-2109:00borkdudeah right#2021-01-2109:00borkdudeI wonder if you could do this with a hook. I think you could but the namespace is currently not passed to the hook function. Can be added though.#2021-01-2109:01borkdudeHow is ig/init-key :foo/bar ok here though?#2021-01-2109:03borkdudeshouldn't this be :foo.bar/something?#2021-01-2109:05rickmoynihanno its ok because there are two rules for matching… I forget exactly but something like: 1. if you have the key :foo/bar try first to load the namespace foo.bar 2. if that fails try the namespace foo (and expect to find the ig/init-key :foo/bar in it)#2021-01-2109:06rickmoynihani.e. sometimes a namespaced keyword might fully identify a namespace (and a single component). Other times a namespace might contain many components; either is fine.#2021-01-2109:07rickmoynihanmy example is perhaps a bit confusing because I combined all the examples in a single ns. See here for the official docs: https://github.com/weavejester/integrant#loading-namespaces#2021-01-2109:08borkdudeFeel free to post issues about both your ideas#2021-01-2109:08rickmoynihanThanks, will do :thumbsup: just wanted to check they seemed feasible#2021-01-2217:20borkdude@didibus I just had another idea. Maybe clj-kondo can be equipped with a small nREPL client to double-check if some vars really don't exist, instead of a runtime plugin which you have to run yourself. Haha, wild idea.
#2021-01-2219:34didibusHum, could it be made into a middleware maybe?#2021-01-2219:35didibusI have to say all the runtime things start to confuse me lol. Especially, I get confused how different it becomes then to what Cider does with nRepl already#2021-01-2219:36borkdudeYeah. Or maybe nREPL isn't such a good idea since it excludes other tooling like socket REPLs, so maybe it should be its own thing that clj-kondo can talk with. Just a one time data dump that you run every once in a while is easier#2021-01-2219:36borkdudeAnd possibly this can work for CLJS as well#2021-01-2219:54didibusHum. Well I was thinking. If say you had it as just a command: clj-kondo --runtime-analyze or something like that. Then I was wondering, could the editor, like in Anakondo, I could have an editor command that runs it on your project. And I could run it on your project the first time you open it up as well. Something like that. So maybe you don't need to "connect" to a REPL, maybe it could be something the editors integrate with.#2021-01-2219:55didibusIn fact, could be an option to the analyzer, so it analyzes but also loads all ns, evals all top level forms, and returns the analysis from that, as well as populate the cache.#2021-01-2219:56didibusThat way the analysis would also be able to list those vars that are created by the macros, and it could use it to auto-complete them and all.#2021-01-2219:56borkdudeTo load "all ns" you need to have a classpath. clj-kondo doesn't have a notion of classpath, it just takes what you feed it to --lint#2021-01-2219:57borkdudeclj-kondo would have to invoke a JVM and/or the CLJS analyzer in the JVM#2021-01-2219:57didibusYa, but the editor has a notion of classpath, so I could pass it to clj-kondo.#2021-01-2219:57borkdudeThat is right, you would get all the vars created by macros, that is the idea.#2021-01-2219:58didibusThis might work better with the non native clj-kondo I guess. Would be easier as an alias, then it get the project classpath easilly.#2021-01-2219:58borkdudeyeah, I think a JVM "co-pilot" program would make more sense than letting the clj-kondo binary do this#2021-01-2219:58didibusOk, I see what you mean, ya it might be a seperate tool then I get it now.#2021-01-2220:00borkdudeI think it should be a program similar to https://github.com/clj-kondo/inspector, or maybe it can all live inside that project#2021-01-2220:01didibusIf I think of a nice workflow for it, like personally. I'd have it as part of my build. Like I have a step that compiles my code to see if there is any compile errors, then runs my tests, runs kibit, runs eastwood, runs clj-kondo. I can easily add that tool to this. The nice thing is, I naturally only run this when I know its going to compile, or when I'm about to commit or something like that.#2021-01-2220:02borkdudeYeah, and you can even commit the output of this to source control, like additional "config". https://github.com/clj-kondo/inspector/issues/5.#2021-01-2220:03borkdudeI want it to be useful for editor integration myself, I'm using clj-kondo more during development than in CI#2021-01-2220:03didibusYa, its the ergonomics I'm trying to imagine. If its too REPLy, well, I mean, people already used to Repls and Cider will have no issue. But the aspect of clj-kondo of like: it just works even if I'm a beginner, would be a bit lost to this.#2021-01-2220:04borkdudeyeah, that's why I was thinking, if clj-kondo could peek into a running REPL, this would not require you to run this tool#2021-01-2220:04borkdudeand I could easily bake in some thin nREPL ops into kondo#2021-01-2220:05didibusI'm just wondering, in the REPL, how would you distinguish between a var that ther user defined in the REPL only, and is actually missing from the source code (even in the sense that the code to def it isn't there).#2021-01-2220:05borkdudeI would use the runtime output only as a second opinion to prevent false positives#2021-01-2220:06borkdudee.g. (defvars x y z). x is unresolved, check runtime output, ooh, it's there, ok, ignore.#2021-01-2220:07didibusI guess its because I'm coming from the perspective of tools.namespace refresh. People will often like eval a defn and later delete it. So now if you peek in the REPL, you will see that it is there, but that's the bug they want to be warned against.#2021-01-2220:07borkdudeyeah, that's true, this is also where clj-kondo shines right now: it will tell you the var doesn't exist anymore .. hmm#2021-01-2220:08didibusIts like a battle between false positive and false negative 😛#2021-01-2220:08borkdudeyeppp#2021-01-2220:09borkdudeI'm almost convinced now by your argument that this isn't going to result in an improvement ;)#2021-01-2220:09didibusPersonally, for this use case, I'd lean on false positive. Cause I would see, oh it says that var is missing? Oh but this is a special var being deffed by hugsql, ok let me just add it to the clj-kondo exclusion.#2021-01-2220:09borkdudeyeah#2021-01-2220:10borkdudethe new unresolved var linter saved my ass a couple of times already today#2021-01-2220:10borkdudethanks for leading me through the issue by testing, it really helps to get feedback and not get stranded#2021-01-2220:10didibusI did the easy part 😛#2021-01-2220:10didibusThank you for the hard work#2021-01-2220:12borkdudeno problem. this issue was at the top of the list for a while... I noticed I accidentally made the level :warning by default#2021-01-2220:12borkdudeinstead of :error, but maybe that's a good choice for the initial release#2021-01-2220:12didibusI honestly feel clj-kondo is the game changer Clojure was missing. Like because we can interop with Java, almost all other Clojure libs are redundant, even if I like a good Clojure lib over Java interop, I can easily make without. But, the IntelliJ like instant fedback of squiggly lines like hey this isn't how the syntax works, or like dummy you have a typo, this is what I was missing most from Java and C# 😛#2021-01-2220:13didibusI don't think its possible to try clj-kondo, and then decide to go back to not using it haha#2021-01-2220:13didibusSo thank you for making it!#2021-01-2220:14borkdudeYeah, the initial inspiration was joker: it showed the potential#2021-01-2220:14borkdudeAnd then GraalVM native-image came along, rewrite-clj luckily worked the first time, and boom, the right combination#2021-01-2220:14didibusIts also neat how indirectly, you're leading the way for native compilation of Clojure as well#2021-01-2220:19didibusI also love sci and babashka haha 😂#2021-01-2220:19didibusJust showing my gratitude here. Alright, got to go. Ttyl#2021-01-2220:19borkdudeThanks a lot, cya!#2021-01-2319:56snoe@borkdude can we chat about https://github.com/clj-kondo/clj-kondo/issues/1129 ? I think my view comes down to (s/def ::a) and (def a) are very similar, and in my projects, I would treat both a and ::a as definitions even though clojure or spec, under the hood, is just storing some state for the var and the keyword. In lsp. I appreciate that kondo analysis differentiates between var-usages and var-definitions, and, I think, there's an argument to be made for keywords behaving similarly.#2021-01-2319:58borkdudeThis is very library specific and not a core clojure construct#2021-01-2319:58borkdudeSo if you would do something like this, you would have to include all kinds of library specific code#2021-01-2320:00borkdudee.g. def is a special form in clojure, but any macro can make up any kind of def thing using strings, symbols, keywords, etc. This is user-land behavior#2021-01-2320:01borkdudeWhat I think would be generally possible is a list of all keywords, with filename, location, source form (what we call :str so far) and maybe, for some libs we could add a key that this is the defining location or something#2021-01-2320:01borkdudeBut this will be very custom#2021-01-2320:02borkdudefor clojure.spec it would be a no-brainer#2021-01-2320:02borkdudebut what other libs are using this construct? we can't possibly support all of clojars?#2021-01-2320:04snoeyeah, I agree, it's user-space. But clojure.spec is pretty close to core. And the concept of using a keyword to mean something is generally applicable. One of the things that I ask myself about these analysis prs, is how would one implement linting from this feature?#2021-01-2320:05borkdudeWhen you look at the namespace graph, one could maybe derive the first mention of the keyword#2021-01-2320:05borkdudebut since keywords (e.g. defmethods) are usually used to decouple things, this isn't reliable#2021-01-2320:06snoewriting a sci macro for other libraries that maybe does`(s/def ~name)` would be enough to support re-frame/reg stuff#2021-01-2320:06borkdudewouldn't it be sufficient to get all mentions of a keyword (regardless of alias)?#2021-01-2320:08snoefor lsp it would be sufficient for rename, but there'a goto def/find references (that generally doesn't include the def) that the distinction would be useful for. for linting, I imagine the distinction would allow you to say a spec is unused.#2021-01-2320:11borkdudeIf I would have this use case of unused-ness of a spec, I think I would personally just go through the list of all occurrences of this keyword. Same for re-frame events. Keywords that only occur once are suspicious (for specs, but in general, these are usually typos).#2021-01-2320:13borkdude
(ns foo)
(s/def ::bar int?)
:foo/bar
I think it's a bit weird to say ":foo/bar" is defined somewhere. I need to think about this a bit more.
#2021-01-2320:14snoeyeah, I agree it's definitely a different way to think about it. When I added that to the lsp parser though, it made a big difference in usability.#2021-01-2320:15borkdudewas this a feature that was supported in LSP before?#2021-01-2320:16snoeyup. my macro-defs were able to treat a call to a symbol like {clojure.spec.alpha/def [:declaration :element]} and I would tag the first arg (the keyword) as a :declaration . Kondo obviously has a different model.#2021-01-2320:20borkdudeSo it would be useful to have this in hooks then I guess.
(reg-keyword-def ....)
or something
#2021-01-2320:20borkdudeand have this built-in for spec#2021-01-2320:20borkdudebrb#2021-01-2320:20snoein the only one usage lint model, I think you'd have troubles if someone simply forgets to s/def so if the user just (->> x (s/validate ::a) (s/conform ::a)) it's moving to a very heuristic approach.#2021-01-2320:22borkdudeso maybe a list of all keywords and some have :def true ?#2021-01-2320:22snoeI haven't looked at hooks much, but yeah, that might do it. It could add an extra flag to :keywords or we could do a similar split of usages/definitions that vars use#2021-01-2320:22snoeaye, that works for me#2021-01-2320:22borkdudere-frame calls this :reg but the intent might be clear#2021-01-2320:22borkdudealright#2021-01-2320:23snoespec might call it a registry as well.#2021-01-2320:23borkdudethat's true#2021-01-2320:23borkdudeok, we can think more about the name, but I think we have an idea what should be done now#2021-01-2320:23snoeyup, thanks a bunch!#2021-01-2320:23borkdudeI'll ask some other people too what they think of this#2021-01-2320:25borkdudehttps://clojurians.slack.com/archives/C03S1KBA2/p1611433527196500#2021-01-2320:26borkdudeWhat if both re-frame and spec use the same keyword to register something?#2021-01-2320:26borkdudeThen you would have two :def true#2021-01-2320:27snoecould be reg-by set, in the code I've run into it hasn't been a concern but it's a good question.#2021-01-2320:28borkdude:def clojure.spec.alpha#2021-01-2320:28borkdude:def re-frame.core#2021-01-2320:28borkdude?#2021-01-2320:28borkdude:registered-by ...#2021-01-2320:28snoecould be, not sure how hard that would be#2021-01-2320:29borkdudeMaybe :registered-by clojure.spec.alpha works. :registered-by clojure.core/add-watch#2021-01-2320:29borkdudewell in hook code this is easy, since you know what macro you are dealing with#2021-01-2320:33snoeok I can start moving the pr towards this.#2021-01-2320:51borkdudeyeah, we can do :def <truthy> where truthy is either a boolean or the macro / fn that registered it#2021-01-2321:24borkdude@U0BUV7XSA Since this analysis isn't fully formed in our heads yet, I think the best way forward is to add it as discussed and also write some docs, but comment out the docs (using HTML comments) so it's only private to both clj-kondo and clojure-lsp for now, so we have freedom to make changes until we are satisfied.#2021-01-2406:58didibusLet me think through the use cases here... sorry if I'm repeating what you both discussed already. It seems the benefit here is to be able to do go to definition. There is also find reference, but I think that's covered just by having analysis return all keywords and where they are found correct? For go-to-definition we need to know which of the many places the keyword is used in its canonical definition. Figuring out what is canonical is the hard part. Ya, I can imagine if you can teach clj-kondo what functions or macro forms where a keyword appear is the "canonical definition" for it. That would be neat actually. Like @borkdude said, its possible more than one thing define things with the same keyword. So I'm guessing it needs to be each keyword can have 0 or more definitions. And the editor needs to support listing multiple choices when you do go to definition. I can do that in Anakondo easily, not sure if LSP supports this? Now there's the issue of when things are defined dynamically, so now where do you go? Can clj-kondo be smart enough to learn about those as well, and give us the place where the keyword will get dynamically defined? That's what you meant by supporting hooks for it @borkdude? And a nice linter for this would be that say if you are inside of a spec function, and you use a keyword that is not defined anywhere it warns.#2021-01-2407:01didibusSomething else I'm thinking, on a similar vein, it be nice if when auto-completing keywords, it could show only keywords that are relevant. So if you s/def some keyword, and then you s/validate like only keywords that have been s/def should show up in the auto-completion. Just thinking how to do this...#2021-01-2407:09didibusAlso, why not make it a separate entry like var-definitions? Maybe I understood wrong, but it sounded here you wanted on keyword-usages to add a :def key?#2021-01-2505:22snoeI think the reasoning for keeping it all in a single entry is because the interpretation of a keyword as a def is up to userspace.#2021-01-2505:27snoe> And the editor needs to support listing multiple choices when you do `go to definition`. I can do that in Anakondo easily, not sure if LSP supports this? The protocol seems to allow for multiple definition results it will depend on the clients, as always, to support it.#2021-01-2522:11didibus> I think the reasoning for keeping it all in a single entry is because the interpretation of a keyword as a def is up to userspace. Ok, but I mean we're talking in either case, userspace needs to configure clj-kondo for it no? But, ya ok, I see the point, like it might look weird for the map to be empty most of the time, unless userspace configured some keyword defs#2021-01-2522:12didibusI guess from a consumer perspective, it seems like you'd have a different way to parse symbols from keywords for "go to def" and "find references". Which is why I was wondering like if that made sense.#2021-01-2522:13borkdude@U0K064KQV the idea is that a keyword in and of itself doesn't mean anything. e.g.:
(defn foo [x])
(foo :bar)

;; vs

(defn reg-something [k])
(reg-something :bar)
are analogous, whereas
(def x 1)
has definition meaning regardless of what semantics users give to their functions
#2021-01-2522:14borkdudeThis is something that isn't fully clear to me yet, that's why I propose keeping this analysis output private until it's been used by LSP for a while#2021-01-2522:15borkdudewe could make them separate, but having a list of all occurring keywords seems useful to have anyway for renaming purposes#2021-01-2522:19didibusI feel like either or, we're still adding the concept of keywords can be considered as having a definition no? Even though by default they don't in Clojure, but then per-library or user usage they might. I feel for me its more what's easiest to parse in the analysis structure for the common use. I guess its a small detail, either or you can parse out the information. But say someone runs: "go to definition" on a keyword, now you'd filter through the keyword usage for that keyword for the one with "def = true".#2021-01-2522:20didibusWhere as if it was a separate map, you'd look it up in keyword-usage map#2021-01-2522:21didibusActually, sorry, maybe that's more a general critique. I remember now. When I implemented anakondo, I think I wished that things were pivoted, instead of vector of maps, it be maps of vectors of maps#2021-01-2522:22didibusWhere the map is keyed on the name#2021-01-2522:22didibusI found needed to actually parse everything back into maps indexed on names for the different constructs.#2021-01-2522:23didibusAnyways, might have missed the boat on that now.#2021-01-2522:25didibusI'll be happy either way, if :def is on the keyword map or in a separate one.#2021-01-2522:25borkdude> I feel for me its more what's easiest to parse in the analysis structure for the common use. That's a good point#2021-01-2522:27borkdude@U0K064KQV the reason you get everything as a list is that it's not always clear what the index should be. either clj-kondo does this for you (and has to guess what is the right format), or you do it yourself. if clj-kondo would do this for you and you wanted a different index, then it would be hairy to go from one index to another. the work has to happen somewhere and it's most flexible if that somewhere is the end user#2021-01-2522:27borkdudepeople might also want to index on filename, for example, or namespace and then name, etc#2021-01-2522:28didibusYa, that's true. Actually I can't remember fully, but I probably did end up indexing in a slightly more custom to my needs way.#2021-01-2522:28didibusI think had it been in Clojure, I wouldn't have feel the pain 😛, but transforming datastructures in Emacs Lisp is not as simple haha#2021-01-2522:29borkdudewrite a graalvm binary ;)#2021-01-2522:30borkdudeI think now you could do this part using babashka#2021-01-2522:30borkdudeusing clj-kondo as a pod#2021-01-2522:30didibusYa, I've been considering it. The thing is, with any separate process option, now I need to figure out a protocol to communicate between the editor and that, and the editor needs to manage a long running process, maybe multiple if you have multiple project, etc. And I think there's a lot of brittleness there, and also I'm just re-inventing LSP at this point.#2021-01-2522:30borkdudewe could even let clj-kondo take some processing function that is executed using sci, since it already has sci#2021-01-2522:31didibusHum... like pass it a post-processor on the analysis map, that could be nice.#2021-01-2522:31borkdudeyeah#2021-01-2522:32didibusSo you could use Clojure to re-structure it however is best for your use case, and then your editor gets a JSON in that new structure.#2021-01-2522:32borkduderight#2021-01-2522:33borkdudeI think the function could be applied to the :findings as well, just one function that gets the end result before it's written to EDN or JSON#2021-01-2522:33didibusOk, well, it would be cool. I don't know if I'd say its at the top of the Wishlist though 😛 Even though I'm here complaining about how painful it is to do in Emacs Lisp, that's pain I chose for myself haha#2021-01-2522:34borkdudeI think we have to rewrite emacs to clojure one day ;P#2021-01-2522:35didibusThe only thing I can give props to Emacs Lisp, its use of memory is quite impressive, like its very memory efficient#2021-01-2601:11snoein clojure-lsp, we probably have 4 or 5 things to index on, so I just flatten everything into a singular list and search. if perf becomes. a problem we can reify the indexes we need.#2021-01-2602:40didibusEven for auto-complete?#2021-01-2600:28ericdallo@borkdude any reasons for var-definitions bucket from analysis output doesn't have a :end-row and end-col like locals / local-usages ?#2021-01-2600:29ericdalloIt'd be useful for clojure-lsp since we to know if cursor is insdide a function and show on headerline:#2021-01-2600:30ericdalloATM, we are using the :row :col only, so if user moves from function name, but inside the function we don't show it on headerline:#2021-01-2610:06borkdude@UKFSJSM38 I don't know, feel free to add it#2021-01-2723:29richiardiandreaMan, I am finally getting to use this wonderful tool 😄#2021-01-2723:29richiardiandreaThank you borkdude!#2021-01-2814:57borkdudeIf anyone feels like contributing a pretty straightforward linter: https://github.com/clj-kondo/clj-kondo/issues/1149#2021-01-2814:58borkdudeI can help you point to the spot where you can implement it.#2021-01-2910:31borkdudeMerged support for the core.match/match macro to master now. https://github.com/clj-kondo/clj-kondo/issues/496 Give it a try if you're using this lib.#2021-01-2910:40dharrigan@borkdude I can have a stab at 1149. Feel free to ping me as a DM 🙂 I may have a bit of time over the weekend.#2021-01-2910:42borkdudeSure! The relevant section is here: https://github.com/clj-kondo/clj-kondo/blob/fe45dd7710483965f703a01b52cef8ac6977748e/src/clj_kondo/impl/linters.clj#L481 All used bindings are available there. So when there is a binding that is used and starts with an underscore, a warning should be emitted.#2021-01-2910:44borkdudeThe other relevant bit is here: https://github.com/clj-kondo/clj-kondo/blob/293f777bda157eaa1ebc75f9b2eb124fcf5b25a9/src/clj_kondo/impl/namespace.clj#L232 Maybe that is also a good spot to do it.#2021-01-2910:44borkdudeLet me know if you have any questions.#2021-01-2914:25dharriganRight, have a test and it's failing, which means I know where to make it work 🙂#2021-01-3109:39maxpShould clj-kondo handle such things correctly? https://github.com/seancorfield/honeysql/blob/2793619e50cb651545637072b10d765856f2b784/src/honeysql/core.cljc#L13#2021-01-3109:40borkdude@maxp clj-kondo doesn't know what defalias is, but you can configure it to :lint-as clojure.core/def#2021-01-3109:41maxpok, thank you.#2021-01-3109:43maxpBut as I remember there was no such warnings in honeysql... something was changed in last 2-3 weeks?#2021-01-3109:43borkdude@maxp What changed is that clj-kondo can now detect unresolved vars in other namespaces#2021-01-3109:44maxpGreat!#2021-01-3109:44borkdude{:linters {:unresolved-var {:level :warning}}} is the default setting#2021-01-3109:47maxpmy default config now -
{
  :linters
  {
    :unused-referred-var
    {:exclude 
      {taoensso.timbre  [debug info warn]}}

    :unused-namespace
    {:exclude [taoensso.timbre]}}

  :lint-as 
  {
    mount.core/defstate                 clojure.core/def
    garden.def/defstyles                clojure.core/def
    honeysql.util/defalias              clojure.core/def
      clojure.core/defn
    next.jdbc/with-transaction          clojure.core/with-open}}
probably could help some one else...
#2021-01-3109:48borkdudeI think the next.jdbc one isn't needed anymore since clj-kondo now has built-in support for it, courtesy of seancorfield#2021-01-3109:49maxpo! really? ... that's good#2021-02-0122:35borkdudeFinally installed clojure-lsp in emacs (using the new native binary for macOS). Kudos @ericdallo and @snoe, it's exciting work.#2021-02-0212:44Charlie Briggsjust started working on a project using carmine (https://github.com/ptaoussanis/carmine) and found that it defines nearly all it’s commands dynamically via a macro which reads from an edn file https://github.com/ptaoussanis/carmine/blob/master/src/taoensso/carmine.clj#L205 I think to get clj-kondo to recognise this it’d need a hook defined which essentially uses the same mechanism?#2021-02-0212:47borkdudeyes, are you running into problems using the unresolved var linter? you can just ignore this entire namespace#2021-02-0212:50Charlie Briggsyes that’s the issue. Cool, I’ll just take that route for now#2021-02-0212:54borkdude{:linters {:unresolved-var {:exclude [taoensso.carmine]}}}#2021-02-0305:47pithylesshas someone posted a linter for the else->> macro? It's a mind-bending piece of code and I would happily replace better-cond if it means clj-kondo can better lint my code 🙂 https://gist.github.com/borkdude/93efc3f5978a2ed545553a47caaf7aa8#2021-02-0307:49borkdude@pithyless I think it’s not hard to write a hook for this #2021-02-0307:50pithylessyeah, I figured a hook for this is easier to write, than for parsing better-cond; I was just hoping someone had already done it ;]#2021-02-0307:51pithylessif no one has, I guess I'll take a stab at it later#2021-02-0313:28flowthingI'm trying out the new "unresolved var" linter. I'm wondering why it doesn't always work. Repro:
(require '[clojure.tools.namespace.repl :as t.n.r])
(t.n.r/nope)

(require '[clojure.set :as set])
(set/onion)
It reports set/onion, but not t.n.r/nope.
#2021-02-0313:29borkdude@flowthing the reason (probably) is, is that clojure.tools.namespace hasn't been analyzed/linted, but clj-kondo knows about a few built-in libraries like clojure.set already#2021-02-0313:30flowthingAha. Is that something I can fix by configuring clj-kondo?#2021-02-0313:31borkdudeto lint this library, make a .clj-kondo dir in your project root and then lint everything using clj-kondo --no-warnings --parallel --lint <classpath> where <classpath> is some build-tool specific thing like $(clojure -Spath)#2021-02-0313:31flowthingThanks! I'll give that a try. Guess I should RTFM. 🙂#2021-02-0313:31borkdudeIf you use clojure-lsp then it will do this for you, I think#2021-02-0313:31borkdudeany time you open a project#2021-02-0313:32flowthingOK — I don't use it at the moment, though, but good to know.#2021-02-0313:33flowthingYeah, your suggestion fixed the issue -- many thanks!#2021-02-0313:33flowthing(Also for clj-kondo itself — it's absolutely fantastic.)#2021-02-0313:33borkdude🎉#2021-02-0321:58niwinzHi! I have an issue that after some time of digging on it, did not found a solution. I have a macro that "reexports" some vars, so the code looks like (d/export somens/somesymthatpointstovar) , now clj-kondo raises the warning about unresolved var when using anything that is exported using this macro. I tried to use it like lint-as with clojure.core/declare and it does not have any effect (indeed because the warning is not caused by the macro export ; is cause by the use of the results of this macro. There are any hint on how to fix it?#2021-02-0321:58niwinzThanks!#2021-02-0322:00borkdude@niwinz There are multiple ways to solve this. 1) You can configure the :unresolved-var linter to turn off warnings for this namespace. See docs here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-var. 2) You can write a hook to make clj-kondo understand your macro. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md.#2021-02-0322:02niwinzhmm i was not aware about hooks for this case, thanks for the hint#2021-02-0323:15niwinz@borkdude thanks, that worked#2021-02-0704:18ericdalloHey @borkdude I would like to hear your opinion on this clojure-lsp "bug" after the keyword analysis#2021-02-0704:25ericdalloBug: As of now, if there is anyone with a keyword on the project/deps that starts with a number, it'll will not be able to read from cache(sqlite) when starting the project. So, I noticed that every time I start clojure-lsp on clojure-lsp project, it's not being able to read the edn persisted on sqlite, because there is a simple keyword analysis with name :2s from https://github.com/ptaoussanis/encore/blob/645dc120380ab75648cd449c17f24b381055977d/src/taoensso/encore.cljc#L2268. We save the analysis with transforming it to string with pr-string and when load it, we read with edn/read-string . When parsing the edn {:name 2s} , clojrue just throw a NumberFormatException , I tested it on REPL and indeed when you type '2s it just blow up. So i'm not sure what is the issue here, should clojure.data.edn/read-string be able to parse a symbol that starts with a number? otherwise how should we proceed? should clj-kondo save the :name of a keywords bucket with the : ?#2021-02-0709:05borkdude@UKFSJSM38 Storing the name of the keyword as a string would help here. Alternatively clj-kondo could report the keyword as invalid and not output it in the analysis.#2021-02-0709:06borkdudeEDN should not be able to read symbols starting with a number. The spec already says these keywords aren't valid.#2021-02-0709:06borkdudeAlso see https://github.com/clj-kondo/clj-kondo/issues/1160#2021-02-0712:22ericdalloYeah, I see, not reporting probably would be better#2021-02-0712:22ericdalloSince we are parsing a giant analysis from the sqlite and have no way to know which analysis is wrong#2021-02-0712:23ericdalloSo what does that PR merged do?#2021-02-0712:23borkdudebut if clj-kondo offered the name as a string, then it would be ok I think?#2021-02-0712:23ericdalloYes, we 'd persist as a string#2021-02-0712:23borkdudeI reverted the merge, so let's just look at the problem from first principle#2021-02-0712:54ericdalloJust tested and a string value would be parsed correctly from db so probably the best approach for keywords buckets (or all buckets to keep the standard?)#2021-02-0712:55borkdudeWe're already exposing the other buckets as documented features. I kept the keyword analysis undocumented to give it a trial run first#2021-02-0712:56borkdudeMaybe changing all the names to strings won't be a major break though, since (keyword ..) etc take symbols and strings?#2021-02-0712:58ericdalloYes, it takes, looks valid to me#2021-02-0712:58ericdalloCreated thsi to track on clojure-lsp side: https://github.com/clojure-lsp/clojure-lsp/issues/305#2021-02-0713:01ericdalloSomething like that works great for me
(edn/read-string "{:name :2s}")
#2021-02-0713:06borkdudeThis would then be :name "2s"#2021-02-0713:07ericdallooh, yeah, you are right#2021-02-0713:08ericdallowe'd need only the paces that use :name, to parse the string on clojure-lsp, not hard though#2021-02-0713:10borkdudehow are you using :name rigth now?#2021-02-0713:42ericdalloOne place builds the full keyword from a analysis (`:foo/bar` from :alias and :name) and all the others use to compare one keyword analysis with another keyword analysis#2021-02-0713:43ericdalloso, looks changeable#2021-02-0713:44borkdudeyeah, we can change the keyword analysis surely, because no-one else is using that. but I meant the :name fields in the other analysis#2021-02-0713:46ericdallooh got it, let me check#2021-02-0713:46borkdudewe can just change it for the keyword analysis though, PR welcome#2021-02-0713:46borkdudecan do it now#2021-02-0713:49ericdalloyeah, most places we get the string with (name ...) and others we compare with other fields. like :to :from :alias etc, I think would work, but some refacotr/check in all features#2021-02-0713:50borkdudeMaybe strings would have been better to start with. For people using JSON they won't notice the difference but I think there's clojure tooling which might break if we changed that#2021-02-0713:50ericdalloOk, I can do it soon for keywords#2021-02-0713:51ericdalloyeah, for sure, for other analysis we need to be safe#2021-02-0714:10ericdalloJust for reference: https://github.com/clj-kondo/clj-kondo/pull/1162 will make the proper changes on clojure-lsp. thanks#2021-02-0714:10borkdudemerged#2021-02-0714:50ericdalloTested with clojure-lsp and it worked great!#2021-02-0715:00borkdudeyay!#2021-02-0919:31Adam HelinsI have a special macro which is essentially about executing given forms as Clojure code no matter the target platform. (In CLJS, they are evaled during the compilation stage) Is there a way to write a hook for that very special use case? Forcing linting as Clojure? The problem is that in a CLJC file, Clj-kondo will complain if those forms refer to something that is Clojure specific (eg. a call to alter-var-root) because as such, it doesn't know that they will never execute as CLJS.#2021-02-1011:34borkdude@UCFG3SDFV Is it an option to put this code in a :clj reader conditional?#2021-02-1011:35borkdudeIf not, please make a small repro which clarifies the problem#2021-02-1012:53Adam HelinsI tried to make my case here but feel free to close it if you find it to be too narrow of a use case: https://github.com/clj-kondo/clj-kondo/issues/1165 Thanks!#2021-02-1012:56borkdudeWhy don't you suppress unresolved symbol linting for this macro?#2021-02-1012:57borkdude
{:linters
  {:unresolved-symbol
    {:exclude [(your-ns/eval-as-clojure)]}}}
#2021-02-1012:58borkdudeI have another feature in the works to only lint .cljc as one language, e.g. only consider the :clj branches and unbranched code as only clj and ignore the rest.#2021-02-1012:58borkdudeWould that also fit your use case?#2021-02-1012:58borkdudeThis would disable cljs linting for .cljc#2021-02-1013:10Adam HelinsThe thing is, forms passed to such a macro are Clojure forms which should be linted as usual. In that example, Clj-kondo will end up complaining about format because it thinks it is going to be called from CLJS as well. It is essentially about forcing to lint as Clojure in a context where a reader conditional cannot be used. Unfortunately, forcing linting to Clojure in a whole CLJC file would be a heavy price to pay since you would become blind regarding the CLJS side.#2021-02-1013:16borkdudeso the macro is always executed by clojure on the JVM side right? so expanding the macro into #?(:clj the-forms) in a hook would be the correct interpretation?#2021-02-1013:16borkdudethis is currently not possible I think but could be an appropriate solution#2021-02-1013:20Adam HelinsExactly so#2021-02-1013:24Adam HelinsI guess you didn't have many people requesting that. Outside of tooling, I admit I am not sure how useful that would be in "day to day" code#2021-02-1013:26borkdudeyes, but adding the possibility of creating reader conditionals to hook code might be generally useful#2021-02-1013:26borkdudealthough still a bit niche maybe#2021-02-1013:30Adam HelinsUnfortunately I can't help you much since I am not very aware of the inner workings. I've started writing hooks and taking a deeper look only recently#2021-02-1013:32borkdudeI'll leave the issue open and will think about it for a while#2021-02-1011:31neotyk@borkdude https://github.com/clj-kondo/clj-kondo/issues/1164 is this something that would be useful?#2021-02-1011:44borkdudeReplied in the issue#2021-02-1011:56neotykme also 🙂#2021-02-1011:58borkdudeI'll let the issue be open to gather feedback from the community first.#2021-02-1012:15borkdudeIf this doesn't end up in clj-kondo eventually you can write a custom hook to handle cond and condp yourself#2021-02-1012:22neotykhow would I go about writing custom hook, we’ve being bitten in our rear end few times over last days because of condp lacking default case#2021-02-1012:24borkdudeI will write a small one#2021-02-1012:39borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1164#issuecomment-776679048#2021-02-1012:44neotykthank you Michiel#2021-02-1012:46borkdudenp. you might have to do some more work to take into account :>>, e.g. filter it out, but if you're not using that this should already be sufficient#2021-02-1012:49neotykhttps://media.giphy.com/media/dAoa5ivrpbuf5qQZh9/giphy.gif#2021-02-1015:02seriogaIdea for linting: warn about useless -> in the code like (-> 'x). Sometimes during refactoring I remove all forms in threading macro and miss remaining macro itself.#2021-02-1015:11mynomotoMaybe also (-> x y)#2021-02-1015:12borkdudefeel free to post an issue#2021-02-1015:26serioga“Maybe also (-> x y)” NO!#2021-02-1015:30mynomotoWhy? That is like (y x) with extra chars.#2021-02-1015:31mynomotoI'm not talking about when y is a form, that should be fine, but for a symbol or keyword.#2021-02-1015:35seriogahttps://github.com/clj-kondo/clj-kondo/issues/1166#2021-02-1015:40seriogaSometime I would like to emphasize that x is more important in the context than y. Like (f a (-> b xform)). This allows me to place accents. https://clojurians.slack.com/archives/CHY97NXE2/p1612971030126000?thread_ts=1612969334.125300&amp;cid=CHY97NXE2#2021-02-1015:59mynomotoInteresting, never thought about using it that way. Thanks.#2021-02-1015:35seriogahttps://github.com/clj-kondo/clj-kondo/issues/1166#2021-02-1121:37vermaI am running into a slight issue with my own hook to parse one of the om.tools/defcomponentk macros. The macro usage looks like this:
(defcomponentk wow-component [[:data a b c d] [:state wow mate]]
  (display-name [_]
    "Lol")
  (component-did-mount [_])
  (render [_]
          (+ a b c d wow mate)))
#2021-02-1121:39vermaI need all those vars a b c d wow mate be resolved, so I wrote one transformer and right before it returns it does a (prn (api/sexpr new-node)) and shows me this:
(defn wow-component [a b c d wow mate] (letfn [(_ [_] "Lol") (_ [_]) (_ [_] (+ a b c d wow mate))]))
#2021-02-1121:39vermaI am not sure why, clj-kondo still reports a, b, c, d ... all unresolved 😢#2021-02-1121:40vermabasically I am turning the defcomponent into one defn and then wrapping the whole body in one letfn since that was the closest similar structure I could find#2021-02-1121:42vermahere's the code for the hook: https://gist.github.com/verma/58a6c170189b5cf3dc9bf4103ce2e475#2021-02-1121:52borkdudeSo the node is returned? What if you return just a token node, just for debugging? Then it should not report those locals#2021-02-1121:53vermachecking#2021-02-1121:56vermaI tried returning (api/token-node '_) and it said: test.clj::: error: Unresolved symbol: _ which seems right. when I comment out the body and just generate this: (defn wow-component [a b c d wow mate]) .. it shows be this:
test.clj::: error: unsupported binding form a                                                                                                                                                                        │
test.clj::: error: unsupported binding form b                                                                                                                                                                        │
test.clj::: error: unsupported binding form c                                                                                                                                                                        │
test.clj::: error: unsupported binding form d                                                                                                                                                                        │
test.clj::: error: unsupported binding form wow                                                                                                                                                                      │
test.clj::: error: unsupported binding form mate                                                                                                                                                                     │
linting took 13ms, errors: 6, warnings: 0
#2021-02-1121:57vermawonder if there's something about those vars which is not visible when api/sexpr is run on it, printing raw one second#2021-02-1121:58verma<list: (defn wow-component [a b c d wow mate])> ooof that doesn't look right 😕#2021-02-1121:58borkdudewhat doesn't look right about it?#2021-02-1121:59vermahmm, never mind that looks ok#2021-02-1121:59borkdudeare you re-defining defn perhaps in this namespace?#2021-02-1121:59vermaI was wondering if it would show me the types of the vector etc also#2021-02-1121:59vermano I don't think so#2021-02-1122:00borkdudeah#2021-02-1122:00verma
(def wow-component (fn [a b c d wow mate]))                                                                                                                                                                          │
<list: (def wow-component (fn [a b c d wow mate]))>                                                                                                                                                                  │
test.clj::: error: unsupported binding form a                                                                                                                                                                        │
test.clj::: error: unsupported binding form b                                                                                                                                                                        │
test.clj::: error: unsupported binding form c                                                                                                                                                                        │
test.clj::: error: unsupported binding form d                                                                                                                                                                        │
test.clj::: error: unsupported binding form wow                                                                                                                                                                      │
test.clj::: error: unsupported binding form mate                                                                                                                                                                     │
test.clj::: error: unsupported binding form a                                                                                                                                                                        │
test.clj::: error: unsupported binding form b                                                                                                                                                                        │
test.clj::: error: unsupported binding form c                                                                                                                                                                        │
test.clj::: error: unsupported binding form d                                                                                                                                                                        │
test.clj::: error: unsupported binding form wow                                                                                                                                                                      │
test.clj::: error: unsupported binding form mate   
#2021-02-1122:01borkdudeCan you perhaps print the incoming node too?#2021-02-1122:01vermayeah one second#2021-02-1122:01verma
<list: (defcomponentk wow-component [[:data a b c d] [:state wow mate]] (display-name [_] "Lol") (component-did-mount [_]) (render [_] (+ a b c d wow mate)))>
#2021-02-1122:02vermaOne peculiar difference is that now each error is printing twice, instead of once#2021-02-1122:02borkdudeMaybe you can put this code up on Github? Then I'll have a look#2021-02-1122:02borkdudeor is it a work project?#2021-02-1122:02borkdudeIn that case, maybe make a repro repo that I can run locally#2021-02-1122:03vermaI did, the hook code is on the gist I posted#2021-02-1122:03vermabut I can set it up so you can run it easily, one second#2021-02-1122:03borkdudeyes, please set it up completely#2021-02-1122:03borkdudethis will save me time#2021-02-1122:03vermayeah definitely, thanks for your help, I'll ping you here when I have it ready to go#2021-02-1122:12vermaI am sorry @U04V15CAJ but I am an idiot 🙂 .. While I was prepping this for you I found the mistake, I was converting a vector-node to a vector using (api/sexpr) but then adding it back in, I wasn't mapping to tokens back into token-nodes, basically went from:
(api/vector-node flattened)
;; to this ->
            (api/vector-node (map api/token-node flattened))
#2021-02-1122:12vermaplease accept my apology for wasting your time#2021-02-1122:12borkdudeNot a problem. Glad you found it.#2021-02-1122:13verma🙂 thank you!#2021-02-1122:01vermaI changed defn to (def (fn ..)) just to be sure.#2021-02-1122:01vermaalso not sure why printing twice#2021-02-1208:04thumbnailHey; I'm creating an linter (for personal use) for clj-kondo using the hooks.api. First off; props 🍻! I use a replacement for clojure/defn in some cases. Right now I add my macro to :lint-as and add a hook for clojure.core/defn. This works nicely as mything/defn is now recognised and linted properly. I want to detect when clojure/defn is used instead of mything/defn and got a POC working based on the hooks-api. My issue is that i have to match the tag of the node exactly; which can change with other requires/refers. Is there a better way to do this? Thanks 🙂#2021-02-1208:20borkdude@jeroen.dejong I'm not sure what you mean with "match the tag of the node exactly"#2021-02-1208:21thumbnailIn the hook i receive a node, which is the exact symbol it is in the sourcecode. Because mything/defn is linted as clojure/defn, i can't differentiate the two if they're both referred as defn .#2021-02-1208:23borkdudeWhy do you use both lint-as + a hook?#2021-02-1209:39thumbnailI want the clj-kondo built-in defn-linting to keep working#2021-02-1209:42borkdude@jeroen.dejong What do you need the hook for?#2021-02-1209:44borkdudeWhat are you doing in the hook?#2021-02-1210:00thumbnailMy macro uses metadata to do some assertions, (which don't do anything for clj/defn). I'd like a linter which reminds me that i tried to use certain metadata so i should probably use my/defn#2021-02-1210:01borkdudeso you want a hook on clojure.core/defn?#2021-02-1210:06thumbnailYes#2021-02-1210:06borkdudeI think I understand the issue now. https://github.com/clj-kondo/clj-kondo/issues/1170#2021-02-1210:08thumbnailAwesome, thank you 🙂
#2021-02-1210:13borkdudeI just pushed a commit to master. You can download a new binary from the builds in a few minutes for testing#2021-02-1210:24borkdudeLinux binary: https://13196-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2021.01.21-SNAPSHOT-linux-amd64.zip#2021-02-1210:24borkdudemacOS binary: https://13198-176829714-gh.circle-artifacts.com/0/release/clj-kondo-2021.01.21-SNAPSHOT-macos-amd64.zip#2021-02-1210:26thumbnailThat's amazing. I'll check it out in a min#2021-02-1211:56thumbnailNot quite sure how this should work yet, I tried the following: Given these two functions
(my/defn foo [^:tag x] x)
(defn bar [y] y)
(defn fizz [^:tag z] z)
bar is a simple fn,`my/defn` is expected usage (and should be treated as normal defn` , and fizz should report as "did you mean my/defn" because of the ^:tag. I configured condo:
{:hooks {:analyze-call {clojure.core/defn hooks/defn-hook}}
hooks/defn-hook reports fizz correctly :thumbsup::skin-tone-2: . In order to make clj-kondo recognise my/defn as defn, I made a hook which transforms the node as defn. unfortunately that triggers defn-hook too (similar to the lint-as approach).
#2021-02-1211:58borkdudeI think you should do the following:
{:hooks {:analyze-call {clojure.core/defn your-hook}
 :lint-as {your/defn clojure.core/defn}}
#2021-02-1211:58borkdudeso your your/defn calls will be processed as defn (without going through your hook), but the vanilla clojure.core/defn goes through your hook#2021-02-1212:10thumbnailThat works!#2021-02-1212:17borkdudeYou are the same person as Jeroen de Jong right?#2021-02-1212:17borkdudeJust for my info ;)#2021-02-1212:18thumbnailYes 🙂 Figured i'd share it on GH too, for prosperities sake#2021-02-1212:18borkdude:thumbsup:#2021-02-1213:04ericdalloIs there any way to use a hook from other project or something like that?#2021-02-1213:04ericdalloI'd like to use the same hook from rewrite-clj on clojure-lsp : https://github.com/clj-commons/rewrite-clj/blob/v1/.clj-kondo/hooks/rewrite_clj/potemkin/import_vars_with_mods.clj#2021-02-1213:05ericdallodo I need to copy that file or is there a better way to handle that?#2021-02-1213:17ericdalloAlso even copying that, it seems to not work for clojure-lsp project 😕 I have this on my .clj-kondo/.config :
{:hooks {:analyze-call {rewrite-clj.potemkin.clojure/import-vars-with-mods
                        hooks.rewrite-clj.potemkin.import-vars-with-mods/import-vars-with-mods}}
#2021-02-1213:22borkdude@UKFSJSM38 Yes, you can copy/move the hook code to a common directory and then add that directory to :config-paths#2021-02-1213:24ericdallooh, got it, I'll try that#2021-02-1213:47ericdalloSo, not sure what I'm doing wrong, I tryed changing config-paths, or using with ^replace [] just like rewrite-clj does but it's not recognizing the macros#2021-02-1213:48ericdallomy question is#2021-02-1213:48ericdalloShould I have that rewrite-clj.potemkin.clojure/import-vars-with-mods copied besides the hooks.rewrite-clj.potemkin.import-vars-with-mods/import-vars-with-mods ?#2021-02-1213:48ericdalloI thought clj-kondo would search on classpath and find it#2021-02-1213:55borkdudeno, clj-kondo doesn't search hook code on a classpath. it only searches it within your .clj-kondo directory and by extension in :config-paths#2021-02-1213:56borkdudenote that hook code does not need the code that it is about to be available anywhere#2021-02-1213:56ericdalloI see, so it'd be necessary to copy the code from rewrite-clj.potemkin.clojure/import-vars-with-mods too?#2021-02-1213:57ericdalloyeah, I could add it too on .clj-kondo/hooks right?#2021-02-1213:57borkdude> rewrite-clj.potemkin.clojure/import-vars-with-mods this is not hook code right, just JVM code?#2021-02-1213:58ericdallohumm, you are right#2021-02-1220:56vermais there a way for me to return more than one form through my hook function, or I could just do a (do (defn ...) (defn ..)) right?#2021-02-1221:01vermayeah that worked :thumbsup:#2021-02-1222:16borkdude@dharrigan Thanks for the kind sponsorship on OpenCollective!#2021-02-1313:12borkdudeClj-kondo v2021.02.13 New: full support for core.match syntax! And keyword analysis (used by clojure-lsp)! Release notes: https://github.com/borkdude/clj-kondo/blob/master/CHANGELOG.md#v20210213 Happy linting!#2021-02-1416:41borkdudeI made a sponsor channel where I just posted a video in which I go deeper into the new features of the latest clj-kondo. Please let me know if I should invite you to the sponsor channel. You are eligible if you or your company sponsors me, clj-kondo or babashka on Github / OpenCollective.#2021-02-1513:17kommenin our codebase we use a macro for setting up ns aliases without having to require the ns the alias resolves to (for the purpose of namespaced keywords, see https://ask.clojure.org/index.php/2817/lighter-weight-aliasing-for-keywords)#2021-02-1513:19kommenuntil now, we used clj-kondo’s :unresolved-namespace to not warn about usages of those aliases, which we mostly use for only a handful of namespaces. but I’m wondering if I can use the hooks to make it actually lint correctly#2021-02-1513:23kommenmy best guess would be to use the hooks to transform our macro which sets up the alias to a
(require '[foo.bar :as bar])
node, as aliasing with require does work with kondo. would this be a viable approach?
#2021-02-1513:40borkdudeyes, that would be a good way#2021-02-1513:40borkdudesince your company is sponsoring clj-kondo, would you like to have access to the private sponsor channel?#2021-02-1513:41kommenyes, please#2021-02-1515:09Kari MarttilaTrying to use clj-kondo (v2021.01.20) with IntelliJ Ultimate 2020.3.2 and Cursive 1.10.1-eap2-2020.3 with File Watchers as instructed here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/editor-integration.md For some reason I can't see clj-kondo warnings in editor. Trying LSP next.#2021-02-1515:12borkdudeThe clj-kondo LSP jar should work. I am not a Cursive user myself. What I wonder about is if the clojure-lsp plugin works for IntelliJ as well. That would be super awesome, since you get clj-kondo + many other things for free. @ericdallo?#2021-02-1515:31Kari MarttilaOh, god.
LanguageServer for definition
 rawCommand : java -jar /mnt/ssd2/local/bin/clj-kondo-2021.02.13-standalone.jar
not initialized after 15s
Check settings
Programming Clojure without clj-kondo is not worth living - I open my veins. 🙂
#2021-02-1515:35Kari MarttilaAh, I just realized. It's not the lsp version.#2021-02-1516:09Kari MarttilaLSP integration with IntelliJ / Cursive works nicely. I just first didn't realize that I get the warning tooltips only when I first click the yellow triangle in the upper right corner of the editor:#2021-02-1515:35Kari MarttilaStupid me. 🙂#2021-02-1515:43ericdallo@borkdude it should work 🙂 https://clojure-lsp.github.io/clojure-lsp/clients/#intellij-cursive#2021-02-1515:44ericdallousing that Intellij-lsp plugin: https://github.com/gtache/intellij-lsp#2021-02-1516:02kommen@borkdude any hint on how to best create a quoted node in a hook?#2021-02-1516:05borkdude@kommen yes, (api/list-node (list* (api/token-node 'quote) ...))) something like this#2021-02-1516:05borkdudeso generate (quote foo) rather than 'foo#2021-02-1518:47kommenof course 🙈#2021-02-1518:47kommenworks like a charm, thank you!#2021-02-1518:48borkdude@kommen Related, there is also a linter to check alias consistency#2021-02-1518:54kommenyes, we’re using it, very useful. but I don’t see the connection on how this helps me here?#2021-02-1518:54borkdudeit doesn't help, it's only related ;)#2021-02-1518:55kommenok 🙂#2021-02-1518:56kommenbut the nice thing: with that hook for the macro now also lsp-find-references understands the aliases we’re setting up with it. this is so awesome#2021-02-1519:48vemvis there a kondo-based "find usages" thing? Maybe one that I can invoke from the repl? (clj-refactor offers this but it doesn't scale gracefully with project size)#2021-02-1519:48borkdude@vemv clojure-lsp uses clj-kondo to implement this#2021-02-1519:49borkdudeother than that, you can also use the raw :analysis output (exactly the output that clojure-lsp uses)#2021-02-1519:50vemvguess I'll wait for https://github.com/clojure-lsp/clojure-lsp/issues/215 then :) and yes I suspected one can use :analysis - it's simply a matter of putting the time (which someone else might have invested already)#2021-02-1519:52borkdudeThere will be a talk about clojure-lsp Wednesday at the Dutch Clojure Meetup. 20:00 GMT+1#2021-02-1519:57borkdudeonline, in English ^#2021-02-1520:08borkdude@vemv If I understand correctly, you want to leverage the logic from clojure-lsp from the REPL right? That may make sense, maybe clojure-lsp could publish part of their thing as a normal Clojure lib#2021-02-1520:09borkdude^ @ericdallo#2021-02-1520:10ericdalloYes, I'm thinking on this and refactoring clojure-lsp code step by step to make this possible on the future 😄#2021-02-1520:11thumbnailI'm also interested in this. Was actually browsing through clj-lsp's source to find some entry point 😅. (Stuck with raw analysis for now)#2021-02-1520:11ericdallopossible using a Stuart Sierra components arch#2021-02-1520:13ericdallo@UHJH8MG6S I'm thinking about start exposing basic features first, like find-defintiion/references, but still need some hammock time#2021-02-1520:13borkdudeIt might also be cool to do this from the cmd line, like:
clojure -X clojure-lsp/find-usages :var 'foo/bar'
or something.
#2021-02-1520:14ericdalloNot sure yet how we would start, like classpath scan and etc#2021-02-1520:14ericdalloif they are cached like most of the time, this should be fast#2021-02-1520:14borkdudesame as in the editor, if the scan is already there, skip it, else scan#2021-02-1520:15ericdalloYeah, looks good#2021-02-1520:32vemvGood luck with the hammocking :) Looking forward to check out the end result#2021-02-1520:45borkdudeI think a few of these functions could also live in clj-kondo proper, so you would do something like:
clojure -X clj-kondo.tools/find-var-usage :var 'foo/bar' :lint '...'  
but there you would need to pass clj-kondo the (class)paths of the sources to analyze.
#2021-02-1521:04borkdude@vemv Made a POC with commit 6451d5a22bd6bab3098f854d4c50dc704c709f9e
$ clojure -X clj-kondo.tools/find-references :var clojure.core/juxt :lint '["src"]'
{:references
 [{:fixed-arities #{1 3 2},
   :name-end-col 53,
   :name-end-row 301,
   :name-row 301,
   :name juxt,
   :filename "src/clj_kondo/impl/analyzer/namespace.clj",
   :from clj-kondo.impl.analyzer.namespace,
   :col 49,
   :name-col 49,
   :from-var analyze-require-clauses,
   :arity 2,
   :varargs-min-arity 3,
   :row 301,
   :to clojure.core}
  ...]}
#2021-02-1521:04borkdude(I'm pretty sure the API needs more hammock time)#2021-02-1521:07ericdalloLooks cool! I'll try to make something like that using the already existing queries on analysis#2021-02-1522:06borkdudeI think I have a more flexible idea for the command line than building this inside clj-kondo, since everyone is going to want something slightly different anyway. Babashka script to the rescue! https://gist.github.com/borkdude/841d85d5ad04c517337166b3928697bd#2021-02-1600:01vermaI noticed that map-node stuff has been commented out in current master: https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/hooks.clj#L6#2021-02-1600:01vermahow would I go about creating a map-node?#2021-02-1600:02vermaI need to wrap my function args in a {:keys [..]} destructuring .. [a b c] -> {:keys [a b c]}#2021-02-1600:03vermatrying to create a parser for secretary.core/defroute .. which accepts arguments as [a b c] but when the named routes are called they are called as (my-route {:a a :b b :c c})#2021-02-1600:04vermaI can may be generate (defn route-name [args] (let [a (:a args) b (:b args) c (:c args)] ...)#2021-02-1600:04vermabut wondering if a quicker way#2021-02-1600:44vermaI went the wrap-with-let way
(defroute settings "/settings/:view" [view] ...)
==>
(defn settings [args] (let [view (:view args)] ...))
#2021-02-1608:20Bartosz FicHey guys I would like to run clj-kondo in jenkins Pipeline. Can you tell me preferable way to do it ?#2021-02-1608:47borkdude@verma The map-node isn't available since there is also a namespaced-map-node of which the API isn't clear yet in rewrite-clj so I'm hesitant to expose the current one (cc @lee). But so far I haven't needed it to make hook code. Usually you can get away with what's already there.#2021-02-1608:47borkdude@fic.bartosz We have a CI integration doc page here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/ci-integration.md#2021-02-1609:28Bartosz FicI am using Jenkins for CI and I tried to do this in 3 ways: NPM package - I was trying to install clj-kondo as npm package locally in node_modules directory - I tried install it locally in /node_modules/clj-kondo/ - But I am getting error: spawn /node_modules/clj-kondo/unpacked_bin/clj-kondo ENOENT - npm i -g clj-kondo is also not working because I cannot locate clj-kondo from $PATH after installation - It works for me locally (without Jenkins) Command in /usr/local/bin - I was trying to curl the clj-kondo and run it - I've installed it successfully - And after installation Jenkins couldn’t find clj-kondo in $PATH (but it was there) Docker - I was trying to docker run borkdude/clj-kondo container - I had a problem with sharing mounted volume between host container and clj-kondo container - It couldn't even find conf file :( I feel I got stuck. Can you help me ?#2021-02-1609:30borkdude@fic.bartosz I would not use the NPM package personally as it isn't maintained very well.#2021-02-1609:30borkdude/usr/local/bin should work, but which binary did you curl and which OS do you have?#2021-02-1609:30borkdudeThe Docker image is now on cljkondo/clj-kondo btw#2021-02-1609:31borkdudeIf there are any docs mentioning borkdude/clj-kondo they should be changed#2021-02-1609:32Bartosz FicIs cljkondo/clj-kondo on docker hub ?#2021-02-1609:33borkdudeyes#2021-02-1609:34borkdudeWe have docs here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/docker.md#2021-02-1609:34Bartosz FicYou were asking me about os: alpine linux#2021-02-1609:34borkdudeFor Alpine you should download the linux static binary#2021-02-1609:34borkdudethe non-static one doesn't work#2021-02-1613:20Bartosz FicHey I found this issue https://github.com/clj-kondo/clj-kondo/issues/703 and there is url to get artifact. But this url is not working anymore. Can you please share me another url ?#2021-02-1613:21borkdudeYou can download the static binary from the release page, like always: https://github.com/clj-kondo/clj-kondo/releases/tag/v2021.02.13#2021-02-1615:26Bartosz Fic@U04V15CAJ It is working as expected 🙂 Thank you very much for helping me 🙂 Good job !#2021-02-1615:26borkdude:thumbsup:#2021-02-1613:56borkdudeJust published a video about the new clj-kondo release from last weekend here: https://youtu.be/OwekorWK3QA It's about core.match support and keyword analysis used by clojure-lsp.#2021-02-1614:34wilkerluciois there a linter in kondo to give errors when a keyword alias is used, but the namespace isn't imported? I guess that would be something like Unresolved keyword?#2021-02-1614:35borkdude@wilkerlucio
$ clj-kondo --lint - <<< '::str/foo'
<stdin>:1:1: warning: Unresolved namespace str. Are you missing a require?
#2021-02-1614:36wilkerluciooh, my fault, just realized I didn't have kondo setup properly in this project :face_palm:#2021-02-1710:48borkdudeToday I show you how to use babashka and clj-kondo to find var usages in the current project. https://youtu.be/TvBmtGS0KJE#2021-02-1710:50dharriganThat's great! 🙂#2021-02-1711:22codeasoneAny mitigation or advice concerning the following false warning report? Seems to be down to the use of the reader condition # in a cljc file:#2021-02-1711:31delaguardoyou can add a comment to instruct clj-kondo to ignore that problem for :clj
#_{:clj-kondo/ignore #?(:clj [:unused-binding] :cljs [])}
(defn foo
  [x]
  #?(:clj 1 :cljs x))
#2021-02-1711:32delaguardoin fact this is not a false warning report. for cljc files clj-kondo is trying to analyze all contexts (clj and cljs) and your snippet has unused binding for clj scope#2021-02-1711:33delaguardomore info — https://cljdoc.org/d/clj-kondo/clj-kondo/2021.02.13/doc/configuration#ignore-warnings-in-an-expression#2021-02-1711:57codeasoneThanks for the input @U04V4KLKC. It would be nice if I could configure the lint reports so that:
#_{:clj-kondo/ignore #?(:clj [:unused-binding] :cljs [])}
(defn foo
  [x]
  #?(:clj 1 :cljs x))
style "ignoring" is applied across the board for my .cljc files and their associated vars, as I see similar reports quite often in my work project.
#2021-02-1712:00borkdude@U191H9E5C Why would you disable the warning for one language and not the other?#2021-02-1712:00borkdudeYou can simply disable unused-binding warnings for the entire namespace#2021-02-1712:08codeasoneWe have a tree of cljc code containing uix components, which we render server-side and subsequently render in a "rehydrated" context where cljs logic kicks-in. A number of our functions have parameters that are only referenced in the :cljs expressions within the functions, hence the clj-kondo warnings I showed in the example above are prevalent.#2021-02-1712:08codeasoneMost of the time I don't care if a parameter is used in either clj or cljs land, I only care if it isn't used anywhere in a function. Hopefully it makes sense.#2021-02-1712:09borkdudeFeel free to post an issue about this (and I will label it with the sponsor tag :))#2021-02-1718:57borkdudeIf you are interested in clojure-lsp (powered by clj-kondo), @ericdallo will be presenting at the Dutch Clojure Meetup in 5 minutes. Welcome to join. Details here: https://www.meetup.com/en-AU/The-Dutch-Clojure-Meetup/events/trmqnpyccdbnb/#2021-02-1914:17Niklasdoes the :refer linter suppport :exclude? I'm running both clj-kondo and joker, and it seems clj-kondo wants me to :refer :all for clojure.test whereas joker wants me to :refer [deftest]...? I would like to not allow :refer in any other cases.#2021-02-1914:18borkdude@nicke.claesson Can you lint on the command line with clj-kondo only? This way you will exclude any other linting output from this issue, which is often a confusing factor. And then please ask the question again.#2021-02-1914:19borkdudeClj-kondo does not want you to do :refer :all by default (it discourages this for its own analysis good)#2021-02-1914:20Niklasfor code like this [clojure.test :refer [deftest is testing use-fixtures]] I get test/integration/reconciliation_writer_test.clj:6:27: error: require with :refer#2021-02-1914:20Niklaswhich is fair, becuase I want to disallow usage of :refer because then you don't see that functions are external#2021-02-1914:21Niklashowever for macros in clojure.test it makes sense to refer them, I think (t/deftest) is unneccessary#2021-02-1914:21borkdudeOK, I see. The config for this linter is here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#refer and as of now it doesn't support exclusions. But you can ignore the warning locally using #_:clj-kondo/ignore before the form#2021-02-1914:22borkdudeFeel free to post an issue#2021-02-1914:23NiklasI'm more interested in a solution without hacks, so basically you are open to adding the :exclude arg to the :refer linter?#2021-02-1914:23borkdudeyeah#2021-02-1914:23Niklasthanks#2021-02-1914:24borkdude@nicke.claesson One thought: since you will probably also add the same namespace to the exclude for the refer-all, maybe we can make it so that the refer linter also uses that config#2021-02-1914:25borkdudeoh wait, you were not going to do :refer :all, then never mind#2021-02-1914:29Niklasexactly, I won't need :refer :all 🙂#2021-02-1914:54practicalli-johnIs there an annotation I can add to my rich comment blocks that tells clj-kondo to completely ignore the contents for any checks (I am looking at the docs, but trying to fix a broken build)#2021-02-1914:55borkdudeyes, #_:clj-kondo/ignore#2021-02-1914:55borkdudejust place it before the comment form#2021-02-1914:58practicalli-johnAwesome, you have unbroken the build 🙂#2021-02-1914:59dharriganhow about this too? {:skip-comments true} in the config.edn?#2021-02-1915:00practicalli-johnThat is a good idea, once we update the project to deps.edn 🙂#2021-02-1915:01dharriganit's not in deps.edn#2021-02-1915:01dharriganit's the configuration for clj-kondo#2021-02-1915:01dharrigan.clj-kondo/config.edn#2021-02-1915:04practicalli-johnAh, yes, sorry doing many things all at once and all of them are broken 😞#2021-02-1915:19practicalli-johnThinking about this, we only want to skip comments on the build which is done via GitHub actions, so I assume instead of this line in the .yml file
run: lein with-profile test clj-kondo --lint .
we can add the config like this to the .yml file
run: lein with-profile test clj-kondo --lint --config '{:skip-comments true}' .
I guess if I run it I will find out 🙂
#2021-02-1915:23borkdudeyes, you can do that#2021-02-1915:23borkdudeno#2021-02-1915:23borkdude--lint . --config ...#2021-02-1915:23practicalli-johnah, thanks. I'll fix before I push 🙂#2021-02-1915:48ikitommiis there a way to describe HOFs with clj-kondo? e.g. “function takes a function of :int -> :int”. there is :fn and :ifn, but they don’t have type info or arities, I guess.#2021-02-1915:51borkdudeno higher kinded types or even generics in the clj-kondo type system currently :)#2021-02-1920:22EdThat would be a pretty great feature though ... is it on your hit-list??#2021-02-1917:16dviramontesHi, first off - thank you for creating clj-kondo thanks3. It's amazing project. Quick question on the https://github.com/clj-kondo/config. It looks like the recommended way to lint slingshot is https://github.com/clj-kondo/config/blob/master/slingshot/.clj-kondo/config.edn (or at least that's the only way i got it to work). Does anyone have an example of pulling slingshot as a library instead of the manual copy config ? maybe there is something different about slingshot that prevents us from pulling it as a library ?
{:lint-as { slingshot.slingshot ...} }
#2021-02-1917:18borkdude@dviramontes if you put the clj-kondo configs library on your classpath and then lint your classpath using:
clj-kondo --lint $(clojure -Spath) --no-warnings
while you also have a .clj-kondo directory, then clj-kondo will copy the config and it will also propose how you can activate it.
#2021-02-1917:19borkdude
$ clj-kondo --no-warnings --lint "$(clojure -Spath -Sdeps '{:deps {clj-kondo/config {:git/url "" :sha "e2e156c53c6c228fee7242629b41013f3e55051d"}}}')"
#2021-02-1917:20borkdude(you might need to update the SHA)#2021-02-1917:24dviramontesGotcha, thank you so much @borkdude!#2021-02-1917:34practicalli-johnFor a CI environment, if I only want to get error level and skip warnings, would I use the --no-warnings flag as a command line argument? I only want the build to fail on error level linting, skipping warnings that are less important. Or would it be more appropriate to specify a particular config file and somehow suppress clj-kondo warnings in that ci-config.edn file? I guess I could create a ci-config.edn with ignores for the rules we didnt want to stop the build for.#2021-02-1918:13borkdude@jr0cket The, no --no-warnings argument is only used for populating the cache, so you lint, but you will ignore the warnings#2021-02-1918:13borkdudeCreating a ci-config.edn is indeed the one you need#2021-02-1919:17ikitommigiven that a library (here: malli) can emit clj-kondo :type-mismatch configs from a namespace x. is there a convention / place where to write the info so it's picked up automatically?#2021-02-1919:19ikitommiand same question but for the library's own function definitions.#2021-02-1920:28borkdudesame answer applies, I think?#2021-02-1921:18borkdude@ikitommi I am considering a dir structure reflecting the namespaces of the vars being typed if the type output gets too large to read on every clj-kondo startup#2021-02-1921:18borkdudeBut this would only become relevant if people are type annotating lots and lots of functions, which is currently not the case#2021-02-1919:18borkdude@ikitommi Not really, you can write to any dir inside .clj-kondo and then users can opt in to that config using :config-paths#2021-02-1919:19borkdudeThis is opt-in for safety, since I don't want users to automatically opt-in to hook code, etc#2021-02-1920:22EdThat would be a pretty great feature though ... is it on your hit-list??#2021-02-1920:24borkdude@l0st3d Not really, since I don't think you will catch many errors using static analysis.#2021-02-1920:24borkdudeUnless you go fully statically typed#2021-02-1920:29Edyeah ... you're probably right 😉 ... just wondered how far you could go with that sort of analysis ... like maybe as far as the structural typing type thing, so something like
(->> (range 10)
       (map #(array-map :test %))
       (map #(update % :test str))
       (map #(update % :test inc)))
would give an error ... but you're probably right, it's probably way more effort than it's worth 😉
#2021-02-1920:30Edthat's probably a research project ...#2021-02-1920:31borkdudethere's already such a research project and someone who has a PhD on it: @ambrosebs in #core-typed#2021-02-1920:32Edyeah ... that's what I meant 😉#2021-02-1920:33borkdudeIf Clojure becomes popular enough, maybe M$FT will make a TypeScript for CLJ? ;)#2021-02-1920:33Edha#2021-02-1920:36Edit's just I feel like having the type system outside of the compiler (like a linter) is just better design ... you don't need to police it, just inform people of possible problems ... and given that freedom, I wondered if it would be easier to get some quick wins in that direction ...#2021-02-1920:36Edjust an idle thought 😉#2021-02-1920:36Adam HelinsKondo complains that do is redundant, is it?!
#?(:clj  (Long/reverseBytes b64)
     :cljs (do
             (.setBigUint64 -data-view
                            0
                            b64
                            false)
             (.getBitUint64 -data-view
                            0
                            true)))
#2021-02-1920:37borkdudeWell, clj-kondo already has a type system, albeit a simple one which catches many things I found annoying myself.
$ clj-kondo --lint - <<< '(take 10 (map inc))'
<stdin>:1:10: error: Expected: seqable collection, received: transducer.
#2021-02-1920:38Edyup ... and I think it's great ... I find it very ... it catches a lot of the stupid mistakes I make every day ... Thank-you so much for releasing it to the world#2021-02-1920:45Edcould you treat map/`filter` /etc as ->? so that if you can tell what type the elements of the list are, you could turn (map inc (map str (range 10))) into (-> 10 str inc), which could return a warning? ...#2021-02-1920:58borkdudeMaybe, but probably not low hanging fruit#2021-02-1920:37borkdude@adam678 This depends on the context#2021-02-1920:38borkdudeIf there is already an (implicit do) around this, then it could be redundant and you can avoid this using ##2021-02-1920:40Adam HelinsRight, those forms are the body of a function so I should # indeed to be technically correct. Took me a bit off guard.#2021-02-1921:12dviramontesDoes CLJ-Kondo have a way to exclude a namespace from linting ?#2021-02-1921:14borkdude@dviramontes Kind of, you can exclude files from the lint output. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#include-and-exclude-files-from-the-output#2021-02-1921:15dviramontesright on! thank you#2021-02-2011:08borkdude#2021-02-2011:09borkdude^ Posting this here because clojure-lsp uses clj-kondo analysis in a very cool way.#2021-02-2106:24devnI have been spreading the word also. It’s a great project, and I made easy work out of cleaning up some code with it recently.#2021-02-2106:28devnI removed 1k+ lines from a project due to the great unused var tracking across namespaces.#2021-02-2221:03thumbnailHmmm. I'm facing an interesting issue. Running clj-kondo --parallel --lint "$(lein classpath)" takes about 37s to write ~73kb of cache. Running kondo/run! from the lein repl with the same options actually results in OOM after 1.5minutes of running. The repl has a xmx of 1G.#2021-02-2221:04thumbnailThis is the stacktrace.#2021-02-2221:04thumbnailI'm not sure where to start looking. Although i think it's interesting it's reporting around infinite / lazy sequences.#2021-02-2221:09thumbnailIf i 'window' over the dependencies (e.g. call run! in steps of 50/100 files at a time) it's fine.#2021-02-2320:39vemvIsn't a Xmx value of 1G pretty low though? I tend to set it around 18G, even in laptops with 32GB available (64GB currently). Note that such a Xmx does not allocate that much memory upfront: other processes aren't affected unless your java process actually uses that much RAM (which tends to be a transient peak anyway - then GC kicks in and RAM is available system-wide again)#2021-02-2320:40vemvPersonally I tend to have the opinion that Clojure is simply more memory-hungry than Java, so sophisticated programs can have surprising memory requirements, given a sufficiently large input.#2021-02-2320:43vemvThere's a slight (but not strictly related) hint of this here: https://github.com/clj-commons/rewrite-clj/issues/69#issuecomment-767914874 a sophisticated clj program needed a higher stack size simply because of it choice of clojure and recursive algorithms (`clojure.walk`). The interesting part being that there was no 'bug' - simply one needed a -X value that is suitable to the caliber of the program being run#2021-02-2321:08vemv...one cheap experiment you can make is increasing Xmx very (but not exceedingly) generously, say to 8G. Then run clj-kondo while you observe the Heap graph in your visual profiler of choice. Say the heap peaked at 1.6GB. Then it becomes an educated guess to set Xmx at 2G (if you still want that minimalism) and assume that peaks won't OOM you#2021-02-2415:43thumbnailThat's a good idea. I'll try it out soon. 1Gb is relatively low i guess, but it's more than enough for the project i'm running. So I expected (maybe unduly) that clj-kondo wouldn't use a gig just to analyse that project.#2021-02-2310:20jumarWhat's the best way to teach clj-kondo about slingshot's special "features"? E.g. I have this catch clause inside try+ and the linter reports "unresolved symbol" for both status, body, and &throw-context.#2021-02-2310:21borkdude@jumar We have a hook for this in clj-kondo/config: https://github.com/clj-kondo/config#2021-02-2310:23jumarThanks, I'll have to figure out how to include it in my setup 🙂.#2021-02-2310:24borkdudeThis is explained in its README#2021-02-2314:48metameFor the new unresolved-var linter is there a way to exclude namespaces using a wildcard? Whttp://e.ge have yesql bringing in our sql functions using defqueries that are all in namespaces like .queries.yesql.account and I don’t want warnings for any unresolved vars coming from .queries.yesql.* namespaces.#2021-02-2314:50metameEssentially, this is what we’re doing now: https://github.com/clj-kondo/config/tree/master/hugsql but that no longer works#2021-02-2314:50metameafaict#2021-02-2314:50borkdude@U774Z4VJA This should still work if you haven't defined any other vars in those namespaces#2021-02-2314:50borkdudeIf the namespace is empty (as far as clj-kondo is concerned), then it will be ignored with respect to the unresolved-var linter#2021-02-2314:51metameOk, I will play around with it and see. Right now it seems the same as the hugsql example I posted, but will verify.#2021-02-2314:52borkdudeThere should be no file associated with that namespace in the .clj-kondo .cache in this case#2021-02-2314:54metameya still erring. My yesql ns is like:
(ns com.core.db.query.yesql.webhook
  (:require [yesql.core :as yesql]))

(yesql/defqueries "sql/core/webhook.sql")
#2021-02-2314:54metameAnd still getting warning: Unresolved var: yesql.webhook/find-webhook-by-id#2021-02-2314:55borkdudeAt the moment there is no wildcard, but you can turn the unresolved-var linter off for now and post an issue#2021-02-2314:55metameOk thanks, will try to get a min case and post an issue later today or tomorrow. Many thanks @U04V15CAJ#2021-02-2314:56borkdude:thumbsup:#2021-02-2314:59borkdudeBtw, you might be able to disable linting for these namespace completely using the :output config#2021-02-2314:59borkdudethis is based on filename where you can use regex#2021-02-2315:00metameOk cool will look into that as a workaround#2021-02-2411:12borkdudeThis project uses clj-kondo analysis :)#2021-02-2412:38CarnunMPHi. Quick question about unused cljs requires! :)) The following seems to elicit a false positive:
[react-autosuggest :as AutoSuggest] > warning: namespace react-autosuggest is required but never used
There's also an erroneous 'Unresolved symbol' in one of the two places AutoSuggest is passed as a component to https://github.com/lilactown/helix/blob/master/docs/creating-elements.md#-macro $ (???):
($ AutoSuggest > error: Unresolved symbol: AutoSuggest
   {:suggestions ...

...

($ AutoSuggest {:getSuggestionValue get-suggestion-value ...
Now, https://www.npmjs.com/package/react-autosuggest (see pic below) kinda suggests that I should be doing [react-autosuggest :refer [Autosuggest]] or something, not :as. But making this change (and accounting for AutoSuggest -> Autosuggest) breaks things. (Separate issue, but probably because of helix...) So it could be that react-autosuggest is just strange (and I should add an inline reader comment or do some other config, say). Or maybe kondo doesn't realise react-autosuggest is a js module, not a ns? Or something else?
#2021-02-2412:42CarnunMPAlso, my bad if this is more appropriate for #clojurescript! 🙂#2021-02-2412:53CarnunMPOr #helix, for that matter...#2021-02-2413:27borkdude@U018D6NKRA4 Let's start with the first issue#2021-02-2413:27borkdudeCan you make a full .cljs minimal repro for me?#2021-02-2413:43CarnunMPFor sure. On it! 🙂#2021-02-2414:10CarnunMPThis seems to do it @U04V15CAJ: https://github.com/CarnunMP/kondo-repro#2021-02-2414:12CarnunMPIn fact, both the 'required but never used' warning and the 'Unresolved symbol' error show up:#2021-02-2414:15borkdude@U018D6NKRA4 Yeah, this is a known issue. You should use a string namespace when using npm deps.
(ns hello
  (:require ["react-autosuggest" :as AutoSuggest]))

(defn x
  []
  (AutoSuggest))
#2021-02-2414:15borkdudeThis way clj-kondo can distuingish between normal cljs deps and npm deps#2021-02-2414:16CarnunMP🙏#2021-02-2414:16CarnunMPGood to know! Thanks. :)))#2021-02-2422:28borkdude#2021-02-2507:56borkdudeReminder #2021-02-2619:00borkdudeAny thoughts on the proposal for this new linter? https://github.com/clj-kondo/clj-kondo/issues/1179#2021-02-2619:21metameWe try to enforce snake_case keywords. Seems this could conceivably be used to enforce that by providing a regex?#2021-02-2619:22borkdudeyes, you could do that. feedback welcome in the issue.#2021-02-2619:22borkdudehowever, if you interact with a lib which has non snake keywords, how would you get past the linter warnings?#2021-02-2619:28metameYa not sure if it’s actually a good idea yet, just thinking about it 😉#2021-02-2804:51gmercerHi, I could not seem to find the exclude mechanism for ignoring java.lang.* e.g. (Integer/parseInt numstr) , any clues appreciated#2021-02-2807:53borkdude@gmercer please give a full standalone repro and then the expected outcome #2021-02-2808:00gmercer@borkdude I just cloned https://github.com/mogenslund/liquid and ran clj-kondo --lint src/liq/editor.cljc#2021-02-2808:03gmercerIt is a cljc so this command removes the warning cat src/liq/editor.cljc | clj-kondo --lang clj --lint -#2021-02-2808:04borkdudeIf it’s cljc Java interop should not occur outside of branches #2021-02-2808:05borkdudeUnless it targets a different runtime than JVM and JS#2021-02-2808:21gmercerahh - I see#2021-02-2808:22gmercersorry - for what looks like cross-posting - but they were slightly different problems (in my mind)#2021-02-2808:24gmercerPS really enjoying your latest videos .. I was wondering about a bb/graalvm version of liquid .. which requires some understanding of sci+graal, any chance of a video on that topic?#2021-02-2808:24gmercere.g. a tiny project that you could show is not sci compatible, the slight changes to make it so and how that can be graal'd#2021-02-2808:26borkdude@gmercer You need sci if you need eval in your program. If you don't need this, you can possibly just compile it with GraalVM as is#2021-02-2808:27borkdudeI'm not sure what it entails to compile liquid to graalvm. What does it use for UI?#2021-02-2808:28borkdudejava.awt. That should maybe work on GraalVM 21 and only on linux: https://medium.com/graalvm/graalvm-21-0-introducing-a-new-way-to-run-java-df894256de28#2021-02-2808:29borkdude@gmercer The main incompatibility with sci and clojure is the absence of deftype and definterface and some edge cases around defprotocol and reify#2021-02-2808:34gmercer@borkdude liquid is a zero dependency text based vim/emacs mash - beware it may leave you terminal a bit wonky, definitely worth a try#2021-02-2817:44lreadWhat do you think about a linter that warns if you are using a var/ns from a dep that is marked with :no-doc?#2021-02-2817:48borkdude#2021-02-2817:48borkdude@lee That seems interesting, but clj-kondo doesn't know what is a dep and what is your own source#2021-02-2817:50lreadyah, was describing in the abstract, you’d have to tell it to exclude your nses.#2021-02-2818:12borkdudeI've also mean meaning to do something like this for vars from .impl namespaces. Let's think more about it. But first: dinner.#2021-02-2818:12lreadBon appetit!#2021-02-2818:08lreadBTW, liking your vids @borkdude! If I hadn’t chosen to be a frugally retired hobbyist, I’d certainly be sponsoring you (and others). Hopefully my contributions in other areas in some small way make up for my lack of $ sponsorship!#2021-02-2818:10borkdudeIt sure does, don't worry :)#2021-02-2818:11lreadI’d love to see you be able to afford to do OSS as your main job!#2021-02-2819:42borkdude@juhoteperi Thanks for sponsoring me on Github! Would you like access to the private sponsors channel?#2021-03-0109:31juhoteperiThanks! Sure.#2021-03-0113:48borkdudeAnyone using clj-kondo in Cursive? Maybe you could explain @reefersleep in #lsp what it adds to Cursive.#2021-03-0113:49borkdudeAh, you are here :)#2021-03-0116:36tomdI noticed today that the redefined-var linter picks up
(def foo 4)
(def foo 6)
but not
(let [bar 3]
  (def foo 4)
  (def foo 6))
is there a reason for not warning on the second example that I'm failing to see?
#2021-03-0116:54borkdude@tomd This has to do with what clj-kondo considers to be a top level form. E.g. this works:
(comment
  (def foo 4)
  (def foo 6))
but for some of the other constructs it just assumes the user knows what they are doing or the vars are conditionally defined
#2021-03-0116:56tomdthere's something beautifully optimistic about a linter assuming a user knows what they are doing 😆#2021-03-0116:58tomdbut, yes, understood there will be some scenarios where that will be the case. I'm not sure let is often one of them - we have a few places in our codebase where we simply wrap a load of defs in a let to avoid lots of typing the same thing over and over.#2021-03-0117:01borkdudeyeah, I think this could be improved#2021-03-0117:01borkdudeit you want to have a stab at this, it's in analyze-children in clj-kondo.impl.analyzer#2021-03-0117:06tomdyes I'll create an issue and queue the work soon. just looking to add an exception for vars defined inside lets?#2021-03-0117:07tomd(maybe binding too? not sure if there are other things that usually wrap defs... :thinking_face: )#2021-03-0117:08borkdudeI think let is the most common#2021-03-0214:25ericdalloAny reason why clj-kondo warns about only the first unresolved-symbol/namespace of the same symbol?#2021-03-0214:25ericdalloif I have the same unresolved symbol/ns multiple times on the file, clj-kondo only warn the first occurrence#2021-03-0214:26borkdudeTo not annoy you with more info than you probably need#2021-03-0214:26ericdalloI see, clojure-lsp uses the findings to know if should try to suggest a add-require ns#2021-03-0214:26ericdallobut without the finding it doesn't know that it should seek for a code action#2021-03-0214:26borkdudeThat will also be sufficient on only the first probably?#2021-03-0214:27ericdalloI don't think so, we get the findings of the current line, we don't iterate over all the findings of the buffer#2021-03-0214:28ericdalloso on a big buffer, I need to search the first occurrence of the unresolved var to apply the code action#2021-03-0214:28borkdudeAs a user, why would I apply the action on the second unresolved ns instead of the first?#2021-03-0214:31ericdalloImagine a big buffer, where I has the foo/bar on the start of the buffer and on the end, IMO I want to be able to apply the code action on both places, otherwise I need to find the first occurrence that's how cursive handles that too.#2021-03-0214:32borkdudebut the code action only applies something to the ns form. why would you need all places?#2021-03-0214:32borkdudewhat do you mean with "apply the code action"#2021-03-0214:33ericdallolet me show you a minimal repro#2021-03-0214:33borkdudelove it#2021-03-0214:33borkdudeminimal repros I mean#2021-03-0214:37ericdalloWith a code of:
(ns my-ns)

(def some-func []
  (string/split "some-func" #"-"))

;; lots of code

(def other-func []
  (string/split "other-func" #"-"))
I only get a unresolved ns on the first string/split , I'd like to have the same warn on the second split, otherwise that looks a correct code. Also without that finding, there is no way clojure-lsp knows that there is a unresolved ns without that finding
#2021-03-0214:38ericdalloso if I try to lsp-execute-code-action on the last string/split , clojure-lsp will suggest no Add missing clojure.string require#2021-03-0214:39ericdalloIt just seems odd to me, clj-kondo don't report about all the occurrences of a lint, I know this can be sometimes to much info, but is actually a code that is missing something indeed, just like other IDEs and languages do AFAIK#2021-03-0214:42borkdudeBut why would I apply the code action on the second one, if I already see that the first one isn't right, at the moment of typing it?#2021-03-0214:42borkdudeIt's the same for displaying an unresolved var: just once
#2021-03-0214:42ericdallothat's the issue, If I copy a lot of code for another buffer/ns I'll need to check from top to bottom#2021-03-0214:43ericdalloin my case, I copied a schema declaration from a clojrue service to another#2021-03-0214:43borkdudeWhy do you need a finding to infer the alias -> namespace?#2021-03-0214:43borkdudeCan't you add this code action to any alias/foo symbol?#2021-03-0214:43ericdalloto know that we should search for a unresolved ns#2021-03-0214:44ericdalloit' could result in some performance issues#2021-03-0214:44ericdallocheck of require code actions on each alias/foo#2021-03-0214:45borkdudeWe could make this an option in clj-kondo, but I would prefer that the user keeps seeing it as it is now#2021-03-0214:45borkdudeThe reason is that clj-kondo might be wrong and it's really annoying if your buffer is littered with false positives#2021-03-0214:45borkdudeAnd ignoring only the first will ignore all of them#2021-03-0214:45borkdudeElse you would have to ignore all 60 of them#2021-03-0214:46borkdudeAnd lsp already indicates there is an error in the buffer using the top-level thing#2021-03-0214:47ericdalloa clj-kondo flag looks good to me as we could have users migrating from other IDEs and having this behavior. I agree that would be a lot of warnings, but all of them correct, right?#2021-03-0214:48borkdude> all of them correct Not always, that's the false positives I referred to#2021-03-0214:48borkdudeEven in LSP I would prefer if the display was the same, although you could have all of them as data#2021-03-0214:48borkdudeI'll have to think about this#2021-03-0214:50ericdalloI think we can have a hammock time for that, but that is something I always missed from clj-kondo before clojure-lsp 😛 Could be just me, but I prefer a warning if my code is not right and not need to check the whole buffer for the same symbol or something#2021-03-0214:50ericdalloI think if you have a false positive, you need to fix that somehow first, otherwise you will already have some warning somewhere about that#2021-03-0214:51borkdudeThe issue is, like I already explained: if clj-kondo is wrong, which it can be, then it's irritating to have 60 errors instead of just 1. And right now, you can get rid of those, by only ignoring 1 warning with #_:clj-kondo/ignore. This won't work if we emit all of them. Please put that in an issue.#2021-03-0214:52ericdalloI see, it's a tradeoff indeed, other languages follow this way though, like dart, you can suppress a single warning in a buffer just like #_:clj-kondo/ignore , but still other lines will warn about that. Sure, I'll open a issue later about that, thanks 🙂#2021-03-0215:01borkdudeI think this should be a user preference and not a clojure-lsp opinion. We can make toggles for this per linter config#2021-03-0215:03dharriganActually, I'm the same. I always wondered why it only showed the first but not the others. I wouldn't mind it being a toggle. False positives I can deal with 🙂#2021-03-0215:06borkdudeI basically did the same what joker did when I implemented this ;)#2021-03-0215:07borkdudeand personally I like that#2021-03-0216:54danielnealI'm linting a file that has some xml namespaces created via clojure.data.xml/alias-uri. How do I best fix/suppress the unresolved namespace errors for ::<alias>/<keyword>?#2021-03-0216:57borkdude@danieleneal I just fixed this in the latest version, released Sunday#2021-03-0216:57danielnealwow! That's great - how does it work, do I need to do anything special in config?#2021-03-0216:58borkdude@danieleneal No, should work out of the box#2021-03-0216:59danielnealI'll try now#2021-03-0217:02danielnealPerfect 🙂#2021-03-0221:12richiardiandreaHi there, is there a way to tell clj-kondo not to warn me in case of defmulti "unused" bindings? I basically like to leave them there as part of the documentation of the defmulti#2021-03-0221:15mynomotoCan you use _arg?#2021-03-0221:22richiardiandreaI could, if that was the only way#2021-03-0221:22richiardiandreabut it feels like a hack#2021-03-0221:25mynomotoI think it's the usual convention. Not sure if there is a config specific for defmulti.#2021-03-0221:28richiardiandreaI see, thanks, it might be worth an issue but I am going to wait to see if borkdude is around#2021-03-0221:29borkdudeThis question has come up more than a couple of times and I think it's good to make an option for this#2021-03-0221:30borkdudee.g. this question was asked today here: https://clojureverse.org/t/clj-kondo-and-defmulti/7290/3#2021-03-0221:30borkdudeThere are already a couple of options for unused-binding#2021-03-0221:30borkdudeWe can add another one#2021-03-0221:30borkdudeissue welcome#2021-03-0221:46richiardiandreakk thanks @U04V15CAJ will open one#2021-03-0308:17mikejcusackI'm getting a Unresolved namespace user. Are you missing a require? for referencing symbols in my user.clj. Why is this happening when there is a user namespace defined and it doesn't need a require because it's fully qualified?#2021-03-0308:23mikejcusackThe user.clj is in a separate dev/ source directory. I have a .lsp/config.edn, which includes dev/ in the source paths. The error still is present.#2021-03-0308:30mikejcusackAdding a .clj-kondo/config.edn with {:output {:include-files ["^src" "^dev" "^test"]}} resolved the issue. But I'm confused why this is necessary when the .lsp/config.edn is present. This is happening in vscode with Calva.#2021-03-0308:32mikejcusackActually it didn't. It made the linting not work at all.#2021-03-0308:35borkdudeRepro please.#2021-03-0308:44mikejcusackDefine a var in the user ns. Try to reference it with user/foo#2021-03-0308:44mikejcusackUser ns being in dev/#2021-03-0308:45mikejcusackSo my .lsp/config.edn is
{:source-paths #{"src" "dev"}
 :project-specs [{:project-path "deps.edn"
                  :classpath-cmd ["clj" "-A:dev" "-Spath"]}]
 :semantic-tokens? true}
#2021-03-0308:46mikejcusackThe user ns does get cached in .clj-kondo#2021-03-0308:46mikejcusackDoes the same thing in my Doom Emacs setup so it's not Calva specific#2021-03-0308:47borkdudeCan you please make a standalone repro without LSP.#2021-03-0308:48borkdudeSomething that I can run locally#2021-03-0308:48borkdudewith clj-kondo on the command line only#2021-03-0308:48mikejcusackYou don't use lsp?#2021-03-0308:49mikejcusackRunning clj-kondo --lint <file> results in the same output#2021-03-0308:51borkdudeI do use LSP but when posting an issue with clj-kondo, I don't want to use any downstream tools#2021-03-0308:51borkdudeIf it's an issue with LSP, post in #lsp#2021-03-0308:51mikejcusackOk. Well as I said, running it alone results in the same error#2021-03-0308:52borkdudeok, but that's still not a repro that I can run locally. You'll have to provide me with an actual file or repo that I can run#2021-03-0308:52mikejcusack...?#2021-03-0308:52mikejcusackI gave you the steps#2021-03-0308:52mikejcusackCreate a dev/user.clj, put any def in it. Then reference it from src/<something> as user/<def>#2021-03-0308:54borkdudeYou will have to just put a (require 'user) in there for now. Clj-kondo expects this for any namespace you are using#2021-03-0308:54mikejcusackBut that doesn't make sense given it's a fully qualified ns#2021-03-0308:55borkdudeI don't understand.#2021-03-0308:55mikejcusackAnd adding in a ns require [user :as user]doesn't work either#2021-03-0308:56mikejcusackCode can reference a FQDN without a require#2021-03-0308:56borkdudefqdn?#2021-03-0308:56mikejcusackfully qualified domain name#2021-03-0308:57borkdudeThat's not true though. You can't just (foo.bar.baz/x) without requiring foo.bar.baz in general#2021-03-0309:00mikejcusackNot sure what you mean. Open a fresh repl and eval (clojure.string/starts-with? "foo" "f")#2021-03-0309:00mikejcusackAnd as I said, if I require [user :as user] it still doesn't work#2021-03-0309:05mikejcusackdev/user.clj:
(ns user)

(def foo :foo)
src/kondo.clj:
(ns kondo)

(prn user/foo)
deps.edn:
{:paths ["src" "dev"]}
#2021-03-0309:07mikejcusackThis works#2021-03-0309:07mikejcusackBut results in linting error#2021-03-0309:08mikejcusackAnd you can start a repl and (in-ns 'kondo) and then user/foo#2021-03-0309:08mikejcusackAnd it returns the expected :foo#2021-03-0309:10borkdudeAs I said you should add a (require 'user) in your (ns kondo) file#2021-03-0309:10mikejcusackNot necessary as I said and it still results in the linting error#2021-03-0309:11borkdudeok, can you file an issue?#2021-03-0309:12borkdudeFor now you can solve the problem with {:linters {:unresolved-var {:exclude [user]}}} after adding the require#2021-03-0309:13borkdudeit is unusual what you are doing here btw, normally you will not refer to the user namespace from the code in src#2021-03-0309:14borkdudeit's usually the other way around, you will require other namespaces from user and then use them from user#2021-03-0309:15mikejcusackI have dev-time vars defined there and I'm not referring to them in src/ outside of a comment block. I'm referring to them in test/ mostly.#2021-03-0309:17borkdudeyou can also put a #_:clj-kondo/ignore before the comment block or before the form with the warning to disable the warning#2021-03-0309:18borkdudeBut it's still good to post an issue about this so we can improve this#2021-03-0309:19mikejcusackBut I'm seeing the issue. The user ns is special in this case as the repl is loading it at startup. So it's aware of user/foo. But using another ns it isn't working.#2021-03-0310:05danielnealI wonder if it's this: just because something works, doesn't mean it should lint without errors. For example you can :refer :all and the referred symbols will give errors. I know you can use clojure.string/includes? without requiring clojure.string but for other namespaces it is imo better for the linter to suggest that you require that namespace, as it is then clearer for the next reader.#2021-03-0310:07danielnealOh wait, you're saying including (:require [user]) in your ns form doesn't work?#2021-03-0310:08borkdudeWhat is happening (I think) is that clj-kondo overwrites the vars for the user namespace the next time it starts linting a file. Any file basically starts in the user namespace. So after adding the require, he would still get an unresolved-var#2021-03-0310:09borkdudeNot sure what the correct thing to do is, but it really seems like a questionable edge case#2021-03-0310:23mikejcusackI'm not sure why it's such an edge case. There's a valid use for creating vars in the user namespace so that when you start up the repl you have those already set up. Such as defining a connvar for a db connection. Instead of calling it each time I start a repl I just already have user/conn .#2021-03-0310:23mikejcusackAnd fwiw Cursive analyzes this case just fine#2021-03-0310:24mikejcusackclj-kondo is not working with fully qualified namespaces, which is allowed in Clojure#2021-03-0310:24borkdude@U01NYKKE69G Out of curiosity: does Cursive also catch if you write user/foobar if foobar doesn't exist?#2021-03-0310:25mikejcusackhttps://www.clojure.org/guides/learn/namespaces#_require "While vars can always be referred to by their fully-qualified name, we rarely want to type fully-qualified names in our code."#2021-03-0310:25mikejcusackIt does catch that#2021-03-0310:25mikejcusackIt's not ignoring the user ns. It's analyzing the local file#2021-03-0310:25borkdude@U01NYKKE69G This is not generally true. You can only use this after you load the namespace. And generally you should not rely on other namespaces loading those namespaces for you.#2021-03-0310:26borkdudeThe user namespace might be an exception#2021-03-0310:26mikejcusackIt's absolutely true. I already gave you an example. You can use clojure.string without requiring it#2021-03-0310:26mikejcusackThe place where it's inconsistent is in user code, which requires loading the file as you said.#2021-03-0310:26borkdude@U01NYKKE69G This is not true for e.g. (clojure.pprint/pprint {:a 1})#2021-03-0310:27mikejcusackWhich seems like an issue in Clojure itself#2021-03-0310:27borkdudeYou should not rely on the fact that clojure.string was already loaded by some other library#2021-03-0310:27mikejcusackI'm not. Literally start a fresh repl in a new dir and use it. It works#2021-03-0310:27mikejcusackSo does your pprint example#2021-03-0310:28mikejcusackAnd read the link above#2021-03-0310:28borkdude
$ clj -M -e "(clojure.pprint/pprint {:a 1})"
Execution error (ClassNotFoundException) at java.net.URLClassLoader/findClass (URLClassLoader.java:471).
clojure.pprint
#2021-03-0310:29borkdudeI suggest you read this issue: https://github.com/clj-kondo/clj-kondo/issues/339#2021-03-0310:29mikejcusackIt's just like Java. You can always refer to vars by fully qualifying them#2021-03-0310:30mikejcusack
$ clj
Clojure 1.10.2
(clojure.pprint/pprint {:a 1})
{:a 1}
nil
#2021-03-0310:31borkdude
$ clj
Clojure 1.10.1
user=> (clojure.set/union #{1 2 3} #{2 3 4})
Execution error (ClassNotFoundException) at java.net.URLClassLoader/findClass (URLClassLoader.java:471).
clojure.set
user=>
#2021-03-0310:33mikejcusackOk. Well this is quite confusing given the official docs stating you can refer to things by fully qualifying them always#2021-03-0310:33borkdudeNot if the namespace hasn't been loaded yet.#2021-03-0310:34mikejcusackThat's not what always means#2021-03-0310:34borkdudeThe fact that your clojure.pprint example works just means that it has already been loaded by some other tool#2021-03-0310:34borkdudeI suggest you verify this in the #clojure channel and people will tell you exactly what I told you#2021-03-0310:34borkdudeI'm off to other business now#2021-03-0310:34mikejcusackI'm not loading any libs so it's clj repl itself#2021-03-0310:36mikejcusackBut in any case the repl for sure loads the user namespace and it is suggested to add dev helpers in a user.clj to be loaded by the repl automatically.#2021-03-0310:37mikejcusackCursive treats this correctly and reads your user.clj. clj-kondo does not#2021-03-0310:37borkdudeYes, I've already suggested you make an issue on Github about this, I am repeating myself.#2021-03-0310:38mikejcusackI'm not sure why spending all of this time explaining the issue to you is not enough.#2021-03-0310:39borkdudeIs it too much to ask to post your issue on Github so I don't forget about it?#2021-03-0310:41mikejcusackSince you're talking about yourself forgetting being the issue can you not make the issue yourself with the info I've already provided? I've already taken a chunk of my time to help you when I don't even use the tool. I use Cursive. I'm just trying to be helpful.#2021-03-0310:45borkdudeOK, I will write it down somewhere if I have time. I'm kinda busy right now. Thanks for the help.#2021-03-0312:21borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1190#2021-03-0309:16borkdudeReleased a new clj-kondo version 2021.03.03 with some fixes for false positives introduced by the :redundant-expression linter.#2021-03-0315:11imre@borkdude I see the latest tag at https://hub.docker.com/r/borkdude/clj-kondo/tags?page=1&amp;ordering=last_updated is a few months old. Did you stop publishing these?#2021-03-0315:11borkdude@imre Docker images have moved to cljkondo/clj-kondo on Dockerhub#2021-03-0315:12imreAh, thank you. The link in https://github.com/clj-kondo/clj-kondo/blob/master/doc/docker.md contains an extra - then 😉#2021-03-0315:15imresent a quick pr https://github.com/clj-kondo/clj-kondo/pull/1191#2021-03-0315:16borkdudeThanks!#2021-03-0412:57ericdalloCan I have a hook in my ~/.clj-kondo dir? I'd like to create a hook for a common macro used on hundred of clojure projects#2021-03-0412:57borkdudeyes, you can#2021-03-0413:02borkdudeIt might even better to check the hook code into those projects or into the libraries for which the hook code is written for, so your co-workers can re-use them too#2021-03-0413:05ericdalloYes, we already have a common config for clj-kondo 🙂 my idea is add a hook there as well#2021-03-0413:25ericdalloIs there a example of a hook that defines a var-definition? I have a macro that behaves similar to defn with some minor differences, How can I tell to the clj-kondo in the hook that the first arg is the var-definition name ?#2021-03-0413:26borkdude@ericdallo Write a hook that expands into a clojure.core/defn or clojure.core/def node#2021-03-0413:27ericdalloOh got it, I'll give a try#2021-03-0413:28borkdudeIt's basically a macro-expansion with rewrite-clj nodes#2021-03-0413:28borkdudeAnd then you return that node using {:node your-new-node}#2021-03-0413:38ericdalloIt worked, thanks! 🙂#2021-03-0413:39ericdalloBTW, I needed to manually add the with-meta to the analysis correctly work#2021-03-0413:40borkdude@ericdallo That is expected and documented. Maybe for your custom defn you also could have used {:lint-as {... clj-kondo.lint-as/def-catch-all}}#2021-03-0413:40ericdalloI was using that :lint-as for months, but now I want to fix some things from that macro#2021-03-0413:41borkdudeWe could maybe change the behavior of newly created nodes automatically taking over the position of the outer original node, but that might also confuse people when there is a linting warning on the wrong position#2021-03-0413:41ericdalloit's a integration test macro:
(defflow my-integration-test

  [a (my-func)]
  (some-flow)
  [b (other-func)]
  (other-flow))
#2021-03-0413:42borkdudecool#2021-03-0413:42ericdallohttps://github.com/nubank/state-flow#clojuretest-and-matcher-combinators#2021-03-0413:42borkdudeyou can add your hook to this library#2021-03-0413:42borkdudewhen you lint your classpath, then clj-kondo will recognize it#2021-03-0413:43borkdudeas in: copy it to your config dir#2021-03-0413:43borkdudeyou will still have to opt in to the config yourself#2021-03-0413:43ericdallooh, really cool! So I'd just need to add to my config the :hooks map, but not the hooks folder with the hooks since it'd be present on the lib, right?#2021-03-0413:44borkdudeThe docs for this are here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-03-0413:44ericdallooh, it's like magic! really cool#2021-03-0413:46borkdudeyes, and when you have a new version of your library, the hook code is updated as well#2021-03-0413:47ericdalloreally amazing indeed, could I open a PR for https://github.com/clj-kondo/config/tree/master/resources/clj-kondo.exports/clj-kondo adding that state-flow macro later?#2021-03-0413:47borkdudeyeah you could do that, but you could also just add it to state-flow itself#2021-03-0413:47ericdalloYes, I'll certainly add to the state-flow, so maybe we don't need to add to the clj-kondo/config so?#2021-03-0413:48borkdudeyeah, clj-kondo/config is only for hooks that are contributed without being it part of the libraries themselves#2021-03-0415:58ericdalloFTR this is the final hook#2021-03-0415:58ericdallo
(defn ^:private defflow-bindings [nodes]
  (->> nodes
       (filter api/vector-node?)
       (map (fn [node]
              (let [[sym val] (:children node)]
                [sym val])))
       flatten
       vec))

(defn ^:private defflow-flows [nodes]
  (filter (complement api/vector-node?) nodes))

(defn defflow [{:keys [:node]}]
  (let [[name & flows] (rest (:children node))
        new-node (api/list-node
                  (list
                   (with-meta (api/token-node 'defn) (meta name))
                   (with-meta (api/token-node (api/sexpr name)) (meta name))
                   (api/vector-node [])
                   (api/list-node (list* (api/token-node 'let)
                                         (api/vector-node (defflow-bindings flows))
                                         (defflow-flows flows)))))]
    (prn (api/sexpr new-node))
    {:node new-node}))
#2021-03-0415:58ericdalloAnd a sample of usage:
(defflow my-flow
  [a (+ 1 2)]

  (flow "flow-1"
        (match? a
                1))

  [b (+ 1 2)]

  (flow "flow-2"
        (match? a
                b)))
#2021-03-0416:00borkdudeyou can probably combine map + flatten into mapcat#2021-03-0416:00borkdudelooking good, don't forget to remove the prn#2021-03-0416:01ericdallothanks! I tried to change the defn to clojure.test/deftest but it seems to not work#2021-03-0416:02borkdudeyou should probably generate (do (require 'clojure.test) (clojure.test/deftest ...)) in that case#2021-03-0416:02borkdudeif clojure.test has not been required yet#2021-03-0416:03ericdallooh, I see, let me try#2021-03-0416:19ericdalloNot sure if I did correctly the export config#2021-03-0416:19ericdallodoes that looks correct for you? https://github.com/nubank/state-flow/pull/149#2021-03-0416:26borkdudelemme check#2021-03-0416:28borkdude@ericdallo I would use a multi-segment namespace like nubank.state-flow for the hook namespace#2021-03-0416:28borkdudee.g. check here: https://github.com/clj-kondo/config/tree/master/resources/clj-kondo.exports/clj-kondo/claypoole#2021-03-0416:29borkdudenote that here clj-kondo is the org, because this hook is written on behalf of the clj-kondo org#2021-03-0416:29ericdallogot it, let me change it#2021-03-0416:33ericdalloDone, still looks odd to me the path:
resources/clj-kondo.exports/nubank/state-flow/nubank/state_flow.clj
is that right?
#2021-03-0416:33borkdudeyeah, that's right :)#2021-03-0416:34ericdalloAlso I included a:
resources/clj-kondo.exports/nubank/state-flow/config.edn
not sure if this should be in the lib or manually set by user
#2021-03-0416:34borkdudeonly the parts that are relevant for the lib should be in there, including the hook config#2021-03-0416:37ericdalloso it seems correct to me#2021-03-0416:37ericdalloI'll try to generate a snapshot release local and test it#2021-03-0416:37borkdudeyes#2021-03-0416:47ericdalloHum, it didn't work#2021-03-0416:48ericdalloI tried to add to my home config:
{ :hooks         {:analyze-call {
                                state-flow.cljtest/defflow   nubank.state-flow/defflow
                                state-flow.core/flow         nubank.state-flow/flow}}}
#2021-03-0416:48ericdallobut it didn't work as well#2021-03-0416:49borkdudeYou should not have to add this to your home config if you opt-in to your library config#2021-03-0416:49ericdalloYes that's what I thought#2021-03-0416:50ericdalloso maybe the folders hierarchy in the lib are not right#2021-03-0416:50borkdudeRead the part about how to opt in: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-03-0416:53ericdalloI already did it, I tried adding a :config-paths ["nubank/state-flow"] but didn't work 😕#2021-03-0416:53borkdudeis this dir present in your .clj-kondo dir?#2021-03-0416:54ericdalloyou mean the one in the lib or on my home?#2021-03-0416:55borkdudein the project where you imported it#2021-03-0416:55borkdudeor did you import it in your home dir?#2021-03-0416:56borkdudejust tell me where you see the copied files#2021-03-0416:57ericdalloSo, that's what I did: • generated a local release in this branch: https://github.com/nubank/state-flow/pull/149/files • Changed a local project to usethe local release • when I start lsp on the file it does not handle the macro, it was handling when the hook was on my home dir before I move it to the lib#2021-03-0416:58borkdudeYou should read the last part of https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration better#2021-03-0416:58borkdudeWhere is the copied file (if at all)#2021-03-0416:58borkdudeJust give me the full path#2021-03-0416:59ericdallosorry, that last part is not clear to me, should I add that
{:config-paths ["nubank/state-flow"]}
in the lib config.edn?
#2021-03-0417:00ericdalloI don't see any Copied config to message anywhere#2021-03-0417:00ericdallooh found a log message on clojure-lsp:
WARNING: error while trying to read hook for integration.aux.init/defflow: Could not find namespace: nubank.state-flow.
#2021-03-0417:01borkdudeJust try to walk through the docs step by step for the clj-kondo config project example, it should explain itself#2021-03-0417:14ericdalloIt works now, I renamed only the hook file not the ns inside it :man-facepalming: Thanks for the help and sorry for bother you 🙂#2021-03-0417:15borkdudeglad you found it ;)#2021-03-0418:02devnis there any way to show globally unused publics in linting output? I think the answer is no, but I could swear there was a point in time where this was possible…#2021-03-0418:55borkdude@devn This isn't supported out of the box, but you can do this using analysis output: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#unused-vars Private unused vars are reported though.#2021-03-0418:56borkdudeThere is also https://github.com/borkdude/carve to do this for you#2021-03-0420:56devnnice. i was mostly asking because in older versions of clojure-lsp, it’d highlight public global unused vars, and that was very handy for knocking out dead code#2021-03-0421:00borkdudeit can continue to do so, the information is there#2021-03-0421:00borkdudeyou get this with the lens-mode now#2021-03-0421:00borkdude^ @ericdallo#2021-03-0421:02ericdalloyes, we could do the same logic from lenses indeed, just don't know if we should always present that as a warning#2021-03-0421:02ericdallolike for api usages and etc#2021-03-0421:03borkdudemaybe that can be a config, but IMO lens-mode is sufficient#2021-03-0421:03ericdalloyes, a config would work#2021-03-0421:03borkdude@devn#2021-03-0421:05ericdalloActually, a flag for that looks good, I just wonder the default#2021-03-0421:08borkdudeThe default should probably be: disabled#2021-03-0421:09borkdudeit could just be an "info" diagnostic as well, the level could maybe be similarly set as how clj-kondo does it#2021-03-0421:09borkdudeI think I would turn it on sometimes, but not all the time, similar to lens-mode#2021-03-0421:09borkdude(which for me personally is enough)#2021-03-0421:16devnyeah, i can use the lens (and I have been), but the highlight was nice IMO. I’m actually a bit surprised y’all think the default should be disabled.#2021-03-0421:17devnWhen I think about it, I’m not sure why you’d have an unused public fn that is part of an API that doesn’t have a matching test (even if the level of test is as simple as “it exists”).#2021-03-0421:18devnbut I mean, if it’s configurable, no sweat either way#2021-03-0421:19borkdudehighlight as in: not a warning like clj-kondo but something more subtle?#2021-03-0421:19ericdalloYeah, I think the same, I think I'll add something like :public-vars-lint-level :info#2021-03-0421:20borkdudewe could do a highlight the same as when you are on a local?#2021-03-0421:20borkdudesome different color maybe?#2021-03-0421:20borkdudenot sure how this is done. Maybe take it to #lsp?#2021-03-0422:08richiardiandreaDetect unreachable specs - has this idea already been proposed / implemented? https://stackoverflow.com/questions/45819346/how-to-check-the-resolvability-of-clojure-specs#2021-03-0422:13borkdudeunreachable as in unused or unresolvable as undefined - two different things ?#2021-03-0501:12richiardiandreaah good point, I would was thinking more of used but undefined like a (s/keys :req-un [::where]) that does not have corresponding (s/def ::where map?)#2021-03-0518:40eccentric JHey there, trying to read the docs on unresolved-symbol but the link seems to be dead. https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#unrecognized-macros#2021-03-0518:41eccentric JIs there an updated page with that info?#2021-03-0518:41eccentric JCan make a PR to fix it#2021-03-0518:42borkdude@jayzawrotny The link should probably go here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#2021-03-0518:46eccentric JThanks, will create a pr for that momentarily. So if I am understanding it right in my ~/.clj-kondo/config.edn I can put the following?
{ :linters {:unresolved-symbol {my-app.utils/current-file [ns-resolve]}}}
#2021-03-0518:47eccentric JOops I see my mistake, forgot the exclude part#2021-03-0518:55borkdudeThanks for the upcoming PR! Yes, that's right#2021-03-0518:58eccentric J
:linters
 {:unused-import
  {:exclude [(my-app.utils [dbg!])]}}
Is there something similar for unused-import? Got a cljs file importing a cljc macro.
#2021-03-0518:58borkdudeunused-import is for classes#2021-03-0518:59eccentric JMy apologies#2021-03-0518:59eccentric JI see the unused-referred-var now, that makes sense sorry about that!#2021-03-0519:00borkdudeCan you provide an example? It's unlikely that you will need a config for a referred thing that you actually are using#2021-03-0519:00borkdudeNo worries#2021-03-0519:01eccentric J
(ns my-app.utils
  (:require-macros
   [my-app.utils :refer [dbg!]])
  (:require
   [cljs.analyzer]))
#2021-03-0519:01borkdudeIs this .cljs file?#2021-03-0519:01eccentric JCorrect#2021-03-0519:01borkdudeAh you want the dgb! macro available, yes this makes a lot of sense for the config. I do something similar with timbre#2021-03-0519:02eccentric JCool, looks like the example is for that too#2021-03-0519:06eccentric JI seem to be running into trouble with the unresolved-symbol exclusion though:#2021-03-0519:06eccentric J#2021-03-0519:06borkdude@jayzawrotny If that is a .cljc file then you should use reader conditionals#2021-03-0519:06borkdudee.g. *file* is not a thing in CLJS#2021-03-0519:06eccentric J
{:lint-as {kitchen-async.promise/-> clojure.core/->
           kitchen-async.promise/let clojure.core/let}
 :skip-comments true
 :linters
 {:unresolved-symbol {:exclude [(my-app.utils/current-file [ns-resolve])
                                (my-app.utils/dbg! [*file*])]}
  :unused-referred-var {:exclude {my-app.utils [dbg!]}}}}
#2021-03-0519:07eccentric JI recall having trouble with that using reader conditionals but I’ll try again#2021-03-0519:07borkdudewhy have it as a .cljc file at all if it only contains clojure code?#2021-03-0519:10eccentric JMy understanding was that macros have to be in cljc to be used within cljs?#2021-03-0519:11eccentric JThough I suppose for this branch I can remove the conditional#2021-03-0519:11borkdudeno that's not the case, you can put your macros in .clj#2021-03-0519:11eccentric JWell it’s intended to work in both clj and cljs#2021-03-0519:12eccentric JThe current-file function runs in cljs#2021-03-0519:12borkdudeyes, but macros are always executed in clojure#2021-03-0519:12eccentric JOk, I can change it to clj then.#2021-03-0519:12borkdudeYour current-file function runs during macro-expansion in the JVM#2021-03-0519:12borkdude(unless you use self-hosted clojurescript, but even then you can use .clj for macros)#2021-03-0519:14borkdudeClj-kondo assumes code in .cljc files to be valid for both Clojure and ClojureScript outside conditionals. E.g. future is unresolved for ClojureScript, hence you write #?(:clj (future :foo) :cljs :foo)#2021-03-0519:21eccentric Jhttps://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html#gotcha-4-clj-macros#2021-03-0519:22borkdudeThe key point: > First of all - ClojureScript macros are written in Clojure and run during the ClojureScript compilation on the JVM. #2021-03-0519:23borkdudeHe is not suggesting you need .cljc, he only writes that you cannot use reader conditionals to achieve a certain goal#2021-03-0519:23eccentric JOh!#2021-03-0519:24eccentric JI think that’s where I got stuck. Thanks very much!#2021-03-0519:24eccentric JLints clean now too 🎉#2021-03-0519:25eccentric Jbtw do you have a sponsorship thing setup for one-off payments? I kind of have an unwritten rule where if I am wasting maintainers time and it turns out to be on me for not understanding or reading the docs: I donate.#2021-03-0519:26borkdudehaha, don't worry#2021-03-0519:28eccentric JI insist! At least a cup of coffee or a beer. Venmo? Paypal?#2021-03-0519:28borkdudeIf you want to buy me a cup of coffee: https://ko-fi.com/borkdude#2021-03-0519:31borkdudeThanks a lot. I'll be thinking of your beautiful CGI scripts during my coffee tomorrow ;)#2021-03-0519:32eccentric JExcellent!#2021-03-0612:39ikitommigiven a defn in some namespace, e.g. clojure.core/map-indexed, is there a way to programmatically infer the arity information? using clj-kondo? using tools.analyzer? something else?#2021-03-0612:41ikitommialso, getting the argument names would be great.#2021-03-0612:41borkdude@ikitommi you can do this using the analysis output:
$ clj-kondo --config '{:output {:analysis true :format :edn}}' --lint - <<< "(defn foo ([x y] x) ([x y & zs] zs))" | jet --query ':analysis :var-definitions' | puget
[{:col 1,
  :end-col 37,
  :end-row 1,
  :filename "<stdin>",
  :fixed-arities #{2},
  :name foo,
  :name-col 7,
  :name-end-col 10,
  :name-end-row 1,
  :name-row 1,
  :ns user,
  :row 1,
  :varargs-min-arity 2}]
#2021-03-0612:42borkdudeWith argument names:
$ clj-kondo --config '{:output {:analysis {:arglists true} :format :edn}}' --lint - <<< "(defn foo ([x y] x) ([x y & zs] zs))" | jet --query ':analysis :var-definitions' | puget
[{:arglist-strs ["[x y]" "[x y & zs]"],
  :col 1,
  :end-col 37,
  :end-row 1,
  :filename "<stdin>",
  :fixed-arities #{2},
  :name foo,
  :name-col 7,
  :name-end-col 10,
  :name-end-row 1,
  :name-row 1,
  :ns user,
  :row 1,
  :varargs-min-arity 2}]
#2021-03-0612:43ikitommigreat. would you have a clojure code snippet for thatt, e.g. not using via the whole app?#2021-03-0612:44ikitommithere btw a lot of code in clj-kondo, reading it now.#2021-03-0612:44borkdudeyou can get this using (with-in-str expr (clj-kondo.core/run! {:lint ["-"] :config {:output {:analysis true}}}))#2021-03-0612:44borkdudeMore docs here: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#2021-03-0612:47ikitommiok, given that I woud like to run this in a repl, I guess source would be a way to get the expr? I’m getting “Source no found” a lot from that.#2021-03-0612:48borkdudeWhat is your flow?#2021-03-0612:48ikitommiuse case: list vars or read all defn vars in a ns and collect the arities from those.#2021-03-0612:48ikitommi(extract-arities *ns*) kinda helper.#2021-03-0612:49borkdudeI would start with the source from that entire ns#2021-03-0612:49borkdudejust put the entire file through clj-kondo
#2021-03-0612:50ikitommiwhat would be a robust way to get the whole source?#2021-03-0612:51borkdudefrom the REPL? (slurp (io/resource "your_org/your_ns.clj")) probably#2021-03-0612:53borkdude
user=> (require '[ :as io])
nil
user=> (slurp (io/resource "hello_world/main.clj"))
"(ns hello-world.main\n  (:require [clojure.edn :as edn])\n  (:gen-class))\n\n(defn -main [& args]\n  (time (println \"Hello world!\"))\n  (prn (eval (edn/read-string (first args)))))\n"
#2021-03-0612:57ikitommifrom repl spin out of malli:
(io/resource "clojure/core.clj")
; => #object[java.net.URL]

(io/resource "malli/core.clj")
; => nil 
#2021-03-0612:58borkdude.cljc?#2021-03-0612:58ikitommi:face_palm:#2021-03-0612:58ikitommithanks! 🙂#2021-03-0613:04lreadThe .cljc thing comes up from time to time. I wonder showing the platform with the error in some way might help. Maybe not so interesting if error applies to all platforms, but interesting if it only applies to a subset of platforms.#2021-03-0613:06borkdudeHe was trying to read a file with a .cljc extension, but used the .clj extension, this wasn't related to a linting warning#2021-03-0613:06borkdudeBut your idea could be useful#2021-03-0613:07lreadAh did not read carefully, just saw .cljc 🙂, but yeah, I was talking about linting and think it might reduce confusion.#2021-03-0613:39lreadIs it worth me writing up an issue?#2021-03-0613:41borkdudeYes, with examples of the output you'd want to see#2021-03-0613:42borkdudePlease#2021-03-0613:42borkdude:)#2021-03-0613:44lreadHappy to! Also we might have lost the thread of another idea I raised... about a linter warning when a var marked with no-doc meta is called. Can raise an issue for that as well if there is any interest.#2021-03-0613:44borkdude@lee Happy to see an issue on that, but I don't have any ideas on this myself, so if you can be very explicit about how that is supposed to work, please do.#2021-03-0613:45lreadCool, will give it a shot!#2021-03-0613:45borkdudeE.g. it's common to call undocumented vars within your own project, how will you avoid false positives? Using a config?#2021-03-0613:46borkdudeThinking of it, maybe it's ok if that var is called from http://your.org but not from http://someone-elses.org namespace#2021-03-0613:46borkdudeor something like that#2021-03-0613:48lreadYa, you’d exclude your own nses.#2021-03-0620:20lreadOk, here’s 1 of 2: https://github.com/clj-kondo/clj-kondo/issues/1196#2021-03-0621:06borkdude@lee Generalizing this idea, I think we could make it configurable to see more info behind the message in brackets. E.g. {:suffix {:language true, :linter-key true} and then you will see for e.g.:
#?(:cljs x :clj y)
1:6: Unresolved symbol: x [cljs, :unresolved-symbol]
1:10: Unresolved symbol: y [clj, :unresolved-symbol]
#2021-03-0621:08borkdudeI think clojure-lsp already shows the linter key in the "suffix" but this could be pluggable. Maybe using a sequential to indicate the order: {:output {:suffix [:language :linter-key]}} (so you will first get the language and then the linter key)#2021-03-0621:33lread2 of 2: https://github.com/clj-kondo/clj-kondo/issues/1197#2021-03-0621:36lreadOh… I did not realize there was not a separate format available for editors. They just parse the terminal output from clj-kondo?#2021-03-0621:38lreadAh I see, there are options.#2021-03-0621:40lreadSo, at the terminal, I don’t think (?) I really need the linter-key but that can be suppressed if I understand you.#2021-03-0621:40borkdude@lee They either parse the terminal output or use something like JSON#2021-03-0621:40borkdudeor in the case of Clojure LSP they just get EDN in the same process#2021-03-0621:41borkdudewell, my idea was to make this optional, so you can configure it how you like and if you don't do anything it stays like it is now#2021-03-0621:41lreadAnd whatever format makes sense is whatever format is most convenient to the editor env I suppose.#2021-03-0621:41borkdudeThe current format is a pretty standard format which vim and emacs get out of the box, so we better not mess with that#2021-03-0621:41lreadgotcha#2021-03-0621:41borkdudebut adding things at the end works#2021-03-0621:42lreadcool!#2021-03-0621:44lreadI think your suffix idea makes sense.#2021-03-0621:45lreadIf the linter issue was for both clj and cljs would both languages be shown?#2021-03-0621:46borkdudehmm, good point...#2021-03-0621:47borkdudewell no, because you actually currently get only one warning because there is a distinct call somewhere#2021-03-0621:47borkdudeI think if we would add the language you would get two different warnings#2021-03-0621:48borkdudethis is just how .cljc is processed: it's linted twice, once for each language#2021-03-0621:49lreadyeah, maybe not as terse, but certainly tells the user what they need to know.#2021-03-0712:42borkdudeFound a .cljc case where I'll definitely write a linter for:
(deftest foo-test
  #?(:clj
     (testing "foo"
       (prn :x))
     (testing "bar"
       (prn :y))))

lein test sci.reify-test
:x

(note: no :y)
#2021-03-0913:40Volodymyr HuzarI have a problem with linting usage of plumbing.core/?>
(let [live? true]
  (-> {}
    (plumbing.core/?> live? (assoc :live live))))
I am receiving two :invalid-arity errors
error: Insufficient input.
error: Expected: associative collection or nil, received: keyword.
Any thoughts on how to fix or ignore linting where it is used?
#2021-03-0913:42borkdudeIs this macro syntactically similar to one in core?#2021-03-0913:44borkdudeit seems similar to cond-> am I right?#2021-03-0913:48borkdude@vguzar I think this macro can be regarded as deprecated in favor of clojure.core/cond-> which I think does the same, but I could be missing something#2021-03-0913:49borkdudeBut if you want to keep using it, you can use {:lint-as {plumbing.core/?> clojure.core/cond->}}#2021-03-0913:51Volodymyr Huzarseems like you are right that cond-> should be used instead, but I don’t think :lint-as will work as it is used differently but let me check. By the way is it possible to deprecate by clj-kondo?#2021-03-0913:52borkdudeYou mean say in your config: I regard these functions are deprecated, so give me a warning when you use them?#2021-03-0913:53Volodymyr Huzaryes, something like that#2021-03-0913:54Volodymyr Huzaras I suspected lint-as doesn’t help, ” No matching clause: “?>“” is shown as an error#2021-03-0913:54borkdudeWe do have a deprecated var linter: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#deprecated-var But no way to add your own vars to that. That could be useful, but it's done automatically if the var is marked deprecated in the library already#2021-03-0913:55borkdudeThat's a weird error message. Let me try this.#2021-03-0913:59borkdudeI can reproduce that, but it seems like a bug#2021-03-0914:00Volodymyr HuzarIt could be useful to have your own set of deprecated 3rd party stuff, like stop use that and start use this instead#2021-03-0914:01borkdudeyeah, I agree. similar stuff has been considered for clojure.core/read-string for example, but there are cases where you still might want to use that#2021-03-0914:02borkdudebut if a var is deprecated in favor of something else that is compatible then that config would make sense for :deprecated-var {:deprecated-var {foo.bar/baz foo.bar/quux}} => Var foo.bar/baz is deprecated. Use foo.bar/quux instead#2021-03-1015:14teodorlu
{:deprecated-var {foo.bar/baz foo.bar/quux}}
Shot from the sideline, I'd prefer to be able to specify both what should be used instead (quux), and the reason for deprecation. So if you're designing a data structure for this, I'd put a map on the right side. Example:
{:deprecated-var {foo.bar/baz {:use-instead foo.bar/quux
                               :reason "baz has a bad API design, it doesn't handle X use case"}}}
#2021-03-1015:15borkdudeyes, good idea. I also want to put a map in between: {:deprecated-var {:some-name {foo.bar/baz ...}}} but I don't know what this name should be#2021-03-1015:16teodorluSomething like
{:deprecated {:vars {foo.bar/baz {:use-instead foo.bar/quux
                                  :reason "..."}}}}
? Not sure what you want to achieve.
#2021-03-1015:18borkdudeUsually the structure is {:linter-name {:exclude {...}} so every setting has an explicit name within the linter map#2021-03-0914:11Volodymyr Huzarand here I have another question which could be related to what you have said in corner cases. Is it possible to mark some rules not be run on specific namespaces. For example I want
:private-call
rule fails on production code but ignore it for tests. Could I use something like
:private-call {:level :error
               :exclude {:namespaces [".*-tests$"]}} 
?
#2021-03-0914:14borkdudeIn tests you can use #'my.private/var#2021-03-0914:16borkdudeor you can turn it off in the namespace config:
(ns foo
  {:clj-kondo/config '{:linters {:private-call {:level :off}}}})
#2021-03-0914:21Volodymyr Huzarso it is not possible to set in configuration that some particular rule will be disabled for all namespaces matching pattern “.*-tests$“, is it?#2021-03-0914:24borkdudeno#2021-03-0914:24borkdudeThis is what you use the namespace local config for#2021-03-0914:25borkdudeAre you using this in ClojureScript? AFAIK the Clojure compiler forbids using private vars unless via the var object#2021-03-0914:37borkdudeCan you create an issue about the deprecated var idea? I am fixing the bug with lint-as + cond-> as we speak.#2021-03-0914:39borkdudeFixed on master#2021-03-0914:50Volodymyr Huzar> Are you using this in ClojureScript? Yes, I’m, probably it should be okay to make them public in such case#2021-03-0914:51borkdudeIn CLJS using #'foo/bar also works#2021-03-0915:20Volodymyr Huzar@borkdude issue for third-party deprecation is created https://github.com/clj-kondo/clj-kondo/issues/1207 Feel free to edit the description by itself#2021-03-0915:31Volodymyr Huzar> In CLJS using `#'foo/bar` also works Maybe I got you wrong but this doesn’t work for cljs. (to add I am not so experience in Clojure syntax 😶) I have tried to change from
(ns test
  (:require [foo :refer [bar]))

(def test-bar bar)
to
(ns test)

(def test-bar #'foo/bar)
and it fixed the linter but broken the test in the same time
#2021-03-0915:38borkdudeYou should still require the namespace#2021-03-0915:38borkdudeYou don't have to define test-bar, you can do it like this:
(ns test
  (:require foo))
(#'foo/bar 1 2 3)
#2021-03-0915:46borkdude
foo=> (ns foo)
WARNING: foo is a single segment namespace at line 1
nil
foo=> (def ^:private x 1)
#'foo/x
foo=> @#'foo/x
1
foo=> (ns bar (:require foo))
WARNING: bar is a single segment namespace at line 1
Execution error (ExceptionInfo) at (<cljs repl>:1).
No such namespace: foo, could not locate foo.cljs, foo.cljc, or JavaScript source providing "foo"
foo=> @#'foo/x
1
This is from a REPL session
#2021-03-0915:50Volodymyr Huzarthanks, by bad knowledge on clojure syntax I have missed @#2021-03-1011:25Volodymyr HuzarI have one more question related to clj-kondo lint-as for plumbing.core I have tried to apply this configuration
:lint-as {plumbing.core/defnk clojure.core/defn
          plumbing.core/letk clojure.core/let}
and as result I get syntax linter error “error: unsupported binding form :events” for
(defnk init [[:events on-select-fn :as events] path]
and “error: unsupported binding form :results” for
(letk [[[:results {result nil} {nextCursorMark nil}]] results]
@borkdude is it expected or it is a bug similar to what was solved yesterday for plumbing.core/?>?
#2021-03-1011:26borkdudeThis is expected since :events is indeed not a valid binding form in defn#2021-03-1011:28borkdudeIf you want to have proper support for these macros you will have to write a hook. https://github.com/borkdude/clj-kondo/blob/master/doc/hooks.md You can contribute it to https://github.com/clj-kondo/config for sharing the hook with others. The other way is to simply ignore unresolved bindings in these macros.#2021-03-1011:29Volodymyr Huzarby ignore do you mean configure somehow clj-kondo to ignore them?#2021-03-1011:29borkdudeyes#2021-03-1011:30borkdude:unresolved-symbol {:exclude [(plumbing.core/defnk)]}#2021-03-1011:36Volodymyr Huzarthanks, it is actually what we are doing right now. I’ll try to look on hooks for the better solution to fix the problem#2021-03-1012:07Volodymyr HuzarActually :unresolved-symbol {:exclude [(plumbing.core/defnk)]} generates new unresolved-symbol errors for declarations inside (defnk fn []) So probably only hooks are the rescue when plubming.core is used 😞#2021-03-1012:23borkdude@vguzar Can you give me a repro of this? I think you should always be able to suppress warnings using config#2021-03-1012:40Volodymyr Huzar@borkdude sorry I have wrongly described the error. When :unresolved-symbol {:exclude [(plumbing.core/defnk)]} is used everything that is declared using defnk of letk became unresolved symbol. For example for all usages of declared request-async
(defnk request-async [{method :get} {headers nil} url {payload nil}])
you’ll get error: Unresolved symbol: request-async
#2021-03-1012:41borkdude@vguzar Ah, for this we have:
{:lint-as {plumbing.core/defnk clj-kondo.lint-as/def-catch-all}}
#2021-03-1012:41borkdudelint-as def-catch-all will use the first symbol as the var name and won't warn about anything else in that defn-like macro#2021-03-1012:42Volodymyr Huzarthanks, that could be a rescue let me try#2021-03-1015:29Volodymyr Huzarworks perfectly, thank you one more time#2021-03-1015:29borkdude:thumbsup:#2021-03-1015:35Volodymyr Huzarsorry for bothering but one error related to `
:unresolved-symbol
which is bothering me and I cannot understand. For this code
(defn set-channels [search {:keys [channel static-channels]
                            :or {channel (:channel search)}}]
clj-kondo complains with error: Unresolved symbol: search The syntax seems to be ok and code is working as it should, any ideas what is wrong here?
#2021-03-1015:38borkdude@vguzar There is an issue about this here: https://github.com/clj-kondo/clj-kondo/issues/916 and https://github.com/clj-kondo/clj-kondo/issues/782 I think this should be supported but was considered not supported in Clojure at one point, but this viewpoint has changed.#2021-03-1015:39borkdudeFor now it's probably best to use a let binding#2021-03-1015:39borkdudeI will bump the priority of issue 916#2021-03-1015:40Volodymyr Huzaroh, thanks#2021-03-1016:19Volodymyr HuzarAnother issue with :unresolved-symbol related to anonymous methods #() and metadata. In this case
#(let [status (.getStatus ^clj %)])
I got an error error: Unresolved symbol: clj Didn’t get the same for regular function definition (fn [^clj xhr]
#2021-03-1016:20borkdude@vguzar Is this .cljc code or only .cljs?#2021-03-1016:22Volodymyr Huzarcljs#2021-03-1016:24borkdudewhat does ^clj mean in the context of .cljs code?#2021-03-1016:31Volodymyr Huzaractually it is a good a question 🙂 I would try to get an answer. Could it influence the fix for linter. I see it used in many places in regular fn but linter is complaining only about anonymous function#2021-03-1016:38borkdudeAh, I see:
(defn foo [^clj x])

(fn [^clj x])

#(do ^clj %) ;; only here
#2021-03-1016:38borkdudeThat's probably a bug in clj-kondo#2021-03-1016:38borkdudePlease post an issue#2021-03-1016:56Volodymyr HuzarIssue https://github.com/clj-kondo/clj-kondo/issues/1212 is here#2021-03-1021:04eccentric JAnyone have an example of a .clj-kondow/config.edn configured for reagent macros to share?#2021-03-1021:07juhoteperiI think only with-let needs to be configured: https://github.com/reagent-project/reagent/blob/master/.clj-kondo/config.edn#L1#2021-03-1021:34eccentric JThanks#2021-03-1021:07juhoteperiI think only with-let needs to be configured: https://github.com/reagent-project/reagent/blob/master/.clj-kondo/config.edn#L1#2021-03-1107:45Karol Wójcik@borkdude I just want to say that clj-kondo is amazing. Thank you very much for bringing it up to Clojure 🙂 I've just configured static typing with #malli & #clj-kondo in Clojurescript for one of the apps based on Rum. Looks awesome! Looking forward to more features in that area!#2021-03-1108:15Karol Wójcik@borkdude One question though 😄 I have the following definition
{:lint-as {malli.schema/defn schema.core/defn},
 :linters {:type-mismatch
           {:namespaces
            {view.home-page {usp-banner*
                             {:arities {1 {:args [{:op :keys, :req {:user-id :number}}],
                                           :ret :any}}},
                             usp-banner
                             {:arities {1 {:args [{:op :keys, :req {:user-id :string}}],
                                           :ret :any}}}}}}}}
and invocation:
(defn usp-banner*
  [props]
  nil)

(defn usp-banner
  [props]
  (usp-banner {:user-id (:user-id props)})

(usp-banner {:user-id "SomeUserIdAsString") 
As for now clj-kondo does no report the type incompatibility. Is there a plan to support it in a future? 🙂
#2021-03-1108:44borkdudeNo plans in the immediate future. This is quite hard to do with static analysis without building something like TypeScript#2021-03-1108:46Karol WójcikActually this would be quite powerful. Typescript for Clojurescript via clj-kondo. There is a huge potential in it 😄#2021-03-1108:48borkdudeYou may post an issue for this specific example so I can see what can be done realistically#2021-03-1108:49Karol WójcikSure! Thank you very much!#2021-03-1119:57gonI'm wondering if (next coll) over (seq (rest coll)) could be a good suggestion candidate for clj-kondo ...#2021-03-1120:19seancorfieldI can't say I've ever seen the latter in code... is that something folks actually do?#2021-03-1120:59gonWell, I know at least one that did it... 😁#2021-03-1120:20seancorfield(I just searched all the OSS projects I have locally and our 110K line codebase at work)#2021-03-1211:21zendevil.ethI’m trying to install flycheck-clj-kondo in spacemacs like so:
M-x package-install flycheck-clj-kondo
#2021-03-1211:21zendevil.ethbut I’m not seeing the flycheck-clj-kondo listed in melpa packages#2021-03-1211:22zendevil.ethI do have the following in user-config#2021-03-1211:22zendevil.eth(require ’package) (add-to-list ‘package-archives ’(“melpa” . “https://melpa.org/packages/”) t) (package-initialize)#2021-03-1211:22borkdudeHave you tried package-refresh-contents ?#2021-03-1211:23zendevil.ethyes#2021-03-1211:24borkdudeI'm not a spacemacs user, maybe try #spacemacs?#2021-03-1211:24borkdudeif all else fails, you can just manually download it to get started#2021-03-1211:26zendevil.ethI mean I have it installed with brew#2021-03-1211:26zendevil.ethwant to use in spacemacs#2021-03-1211:28borkdudeI mean "it" = the elisp package#2021-03-1211:34uoslDoes anyone here run clj-kondo on linux 5.10 (5.10.22_1 specifically)? After updating from 5.9, the clj-kondo linux binaries will segfault when passing --lint flag.#2021-03-1211:34zendevil.ethi installed it using load-file etc.#2021-03-1211:34zendevil.ethBut I don’t think it’s working#2021-03-1211:35zendevil.eth
(defn foo [a b] 1)
(foo)
doesn’t give me a warning
#2021-03-1211:36borkdude@regen which binary are you using?#2021-03-1211:38uoslclj-kondo-2021.03.03-linux-static-amd64.zip#2021-03-1211:39uosli tried the non static as well#2021-03-1211:39borkdude@regen The static one is only intended for Alpine usage#2021-03-1211:39borkdudeThe dynamic one should work. Make sure you remove the static one, so you are not accidentally using it#2021-03-1211:41uosldamn, you're right. I forgot to add ./ when testing the not static. Thanks for your help [=#2021-03-1214:09borkdudeCan someone using Cursive review this PR? https://github.com/clj-kondo/clj-kondo/pull/1214#2021-03-1317:42Ethan MillerWondering if anyone could give me an example of namespace local config for clj-kondo. I've tried:
(ns 
  ^{:clj-kondo/config '{:linters {:unresolved-symbol {:level :off}}}}
  (:require ...))
#2021-03-1317:43Ethan MillerBut I haven't been able to get it to work, and I've not been able to find an example of the syntax in the docs.#2021-03-1317:43borkdude@ezmiller77 That's almost correct, you have to remove the ^#2021-03-1317:43Ethan MillerAhhh#2021-03-1317:43borkdudeYou can use the ^ but then your config needs to go before the namespace name#2021-03-1317:43borkdudeThis is namespace metadata#2021-03-1317:44borkdudeAnd the ns form has special syntax for this: if you put the map after the name it will also work#2021-03-1317:44Ethan Miller🎇 That did it!#2021-03-1317:44Ethan MillerThank you. I think this is my first time adding metadata to the ns form.#2021-03-1317:44Ethan MillerAnd thank you for the VERY fast response!#2021-03-1318:25Ethan MillerIs there a way to avoid an error exit code for warnings?#2021-03-1318:25Ethan MillerOr is this not encouraged?#2021-03-1318:51borkdude@ezmiller77 This is the contract with regards to exit codes: https://github.com/clj-kondo/clj-kondo#exit-codes#2021-03-1323:40Ethan MillerHmmm. I'm using clj-kondo in the context of github actions, which seem to fail on any exit code other than 0. I'm looking around to see if this is something I can configure....#2021-03-1411:07delaguardoGH actions by default failed if exit code is not zero. You can wrap call to clj-kondo in a script which will catch exit code, analyze it and transform it to zero in case there's only warnings.#2021-03-1412:08delaguardo
echo '(def x (def x 1))' | clj-kondo --lint - || if [[ $? = 2 ]]; then exit 0; else exit $?; fi
this snippet pipes output of clj-kondo to simple if/else expression which is transforming exit code 2 (more than one warning found but no errors) to exit 0 indicating that this should be OK result in the scope of GH actions.
#2021-03-1323:40borkdudeMaybe @delaguardo knows the answer here.#2021-03-1323:50Ethan MillerAnother question related to the unresolved-var linter. I'm getting some warnings about unresolved vars in a namespace. I thought the problem was that the namespace used :as instead of :refer but I switched it to refer an am still getting the warning. Any idea what might be happening?#2021-03-1400:43Ethan MillerEnded up adding an exclusion to .clj-kondo/config.edn for now.#2021-03-1405:50ackerleytng
$ clj-kondo --lint project.clj
zsh: segmentation fault (core dumped)  clj-kondo --lint project.clj
Where should I start debugging?
#2021-03-1407:36lispyclouds@ackerleytng are you using the static Linux binary by any chance?#2021-03-1423:41ackerleytngI was! I switched to the regular one and it worked.#2021-03-1505:43lispycloudsFYI, the static one is meant for OSes like alpine which uses musl. On others is a better idea to use the dynamic one. Static binaries have unforeseen issues unfortunately 😕#2021-03-1409:42borkdude@ezmiller77 Unresolved var is usually because some other namespace you are using defines vars using some unknown macro#2021-03-1409:42borkdudeYou can exclude that namespace using :unresolved-var {:exclude [the.ns]}}#2021-03-1510:13raymcdermottI had a bug a little while ago and not sure if it's something that kondo could detect / warn#2021-03-1510:13raymcdermott
(defn any-evens?
  [coll]
  (reduce (fn [_ x]
            (when (even? x)
              (reduced true))) false coll))
#2021-03-1510:14raymcdermott
(any-evens? [2 2])
=> true
(any-evens? [3 3 5])
=> nil
#2021-03-1510:15raymcdermottI wanted false in the second case#2021-03-1510:15raymcdermott
(defn any-evens?
  [coll]
  (reduce (fn [_ x]
            (if (even? x)
              (reduced true)
              false)) false coll))
#2021-03-1510:16raymcdermottgives the correct results ... I know nil is falsey but still#2021-03-1510:16borkdudeNot sure how kondo could help here (in general), as returning nil is valid in reduce functions.#2021-03-1510:17raymcdermott
(defn any-evens?
  [coll]
  (reduce (fn [_ x]
            (even? x)) false coll))
#2021-03-1510:18raymcdermottthis is also correct, though not as efficient#2021-03-1510:19borkdudeWhy not (some even? ....) ?#2021-03-1510:19raymcdermottI'm trying to check whether using reduced and not having another part is flaggable#2021-03-1510:20raymcdermottsure, it was a lot more complex in reality so I'm showing a trivial example ... I want to get to the fact that incorrect use of reduced ... forgetting to assign the result to the accumulator was actually the issue#2021-03-1510:22raymcdermottmaybe I need a better example#2021-03-1611:20ElsoI'm having a problem with clj-kondo integration in emacs, where it sometimes does not lint functions defined in the project but only those defined in required libs. I'm not really certain about how to start debugging that - anybody got a hint maybe?#2021-03-1611:20Elso(it's about number of required args)#2021-03-1611:22borkdudehow are you using clj-kondo, via which plugins#2021-03-1611:25Elsospacemacs clojure layer#2021-03-1611:25Elsoshould be using flycheck/lsp afaik#2021-03-1611:26Elsoweird thing is, it works fine with fns defined in the same namespace, but not in those defined in other namespaces in the same project#2021-03-1611:35borkdudeif you can make a repro using a minimal project + command line examples, I can take a look. Hard to say anything without more details#2021-03-1611:36Elsook#2021-03-1611:25otfromGetting odd false warnings from clj-kondo
(ns witan.small-test
  (:require [tablecloth.api :as tc]))

(defn add-series-name [ds series-name]
  (if (contains? (set (tc/column-names ds)) :series-name)
    ds
    (tc/add-column ds :series-name series-name)))
#2021-03-1611:25otfromall the tc/* things are getting squigglies with the warning Unresolved var:...#2021-03-1611:26otfromnot sure if it is something odd about tablecloth or something in kondo#2021-03-1611:26otfromI'm on the latest kondo release#2021-03-1611:26borkdudeDoth tablecloth define these vars using some custom macro?#2021-03-1611:26borkdudeIf so, then you should either add a config for this custom macro, or add the tc namespace to :exclude in the unresolved-var linter#2021-03-1611:26otfrom
(defn add-column
  "Add or update (modify) column under `column-name`.

  `column` can be sequence of values or generator function (which gets `ds` as input)."
  ([ds column-name column] (add-column ds column-name column nil))
  ([ds column-name column size-strategy]
   (let [process-fn (prepare-add-column-fn column-name column (or size-strategy :cycle))]

     (if (grouped? ds)
       (process-group-data ds process-fn)
       (process-fn ds)))))
#2021-03-1611:27borkdudeand defn = clojure.core/defn? this is not always the case, but I assume it is?#2021-03-1611:27otfromI believe so, but I'm looking#2021-03-1611:28otfromyeah, looks like normal defn (I know potemkin is used in other places, but it doesn't look like in this place)#2021-03-1611:29borkdude@otfrom Maybe re-lint your tablecloth dependency?#2021-03-1611:30borkdudeIf you have some same-named namespace somewhere else it could be that the definitions are overwritten#2021-03-1611:30otfromnever done that before#2021-03-1611:30borkdude@otfrom rm -rf .clj-kondo/.cache should then solve it, but I assume clojure-lsp is linting your deps#2021-03-1611:31otfromit was, but I removed it as that was showing even more weirdness#2021-03-1611:33borkduderepro welcome, need more details#2021-03-1611:33borkdudeWorkaround is {:linters {:unresolved-var {:exclude [.namespace]}}}#2021-03-1611:35otfromseems good now. Not sure how the cache got messed up#2021-03-1611:35borkdudeCould be an issue with lsp + clj-kondo#2021-03-1611:40otfrompossibly#2021-03-1611:40otfromthe cache getting messed up over a number of updates sounds like a reasonable culprit until it happens again#2021-03-1611:40otfromI just had no idea about the cache#2021-03-1611:40otfrom(caches have been the bane of my life recently)#2021-03-1611:41otfromthx for pointing me in the right direction#2021-03-1611:41borkdudeclojure-lsp tries to lint all of your deps automatically. clj-kondo doesn't do this, unless you tell it to#2021-03-1611:41borkdudealso clojure-lsp using an incremental diff when you edit files, which might go wrong - there were some discussions about this in the lsp channel#2021-03-1611:42borkdudeis tablecloth your dep, or your project?#2021-03-1611:43otfromas in did I create tablecloth? I'm just using it#2021-03-1611:44borkdudeyou can try clj-kondo --lint $(clojure -Spath) (assuming deps.edn) and see if you get the issue again#2021-03-1612:58otfromI've run that and I am getting the same issue#2021-03-1612:58otfrom
(ns witan.small-test
  (:require [tablecloth.api :as tc]))

(defn col-wrapper [ds]
  (tc/column-names ds))
#2021-03-1612:59otfromUnresolved var: tc/column-names#2021-03-1613:02borkdudeok, that's what I suspected. taking a look at that api ns: https://github.com/scicloj/tablecloth/blob/master/src/tablecloth/api.clj so these vars are all defined using some custom machinery. you must either configure clj-kondo to make it understand this machinery, or to ignore this#2021-03-1613:03borkdudeit looks an awful lot like potemkin/import-vars but not quite, so you cannot simply use :lint-as for this#2021-03-1613:04borkdudeyou can either write a hook, or use the workaround I suggested. this is expected behavior#2021-03-1614:07otfromthx. sorry for snitch tagging you on zulip, but I was wondering if someone else had already solved it#2021-03-1614:10borkdudefwiw @lee has a nice way to generate the potemkin-like-code using a couple of functions instead of using a macro, this makes all the tooling understand it#2021-03-1614:10borkdudebut writing a hook for this isn't too hard#2021-03-1614:13otfromany examples of other hooks I could crib from?#2021-03-1614:15borkdudehttps://github.com/clj-kondo/config#2021-03-1614:15borkdudemore docs are here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-03-1614:32lreadReferenced in hooks.md, but https://github.com/lread/rewrite-cljc-playground/commit/09882e1244a8c12879ef8c1e6872724748e7914b when I needed it (I no longer do because I abandoned import-vars - too many headaches!).#2021-03-1703:20naomarikI joined just now to express my enormous appreciation for this library and how easy it's making my life. Thanks Michiel!#2021-03-1714:59Alex WhittHas anyone gotten orchestra.core/defn-spec to work? I've seen some chatter about it on here, and it seems like you should just be able to do the following:
{:lint-as {orchestra.core/defn-spec clj-kondo.lint-as/def-catch-call}}
But that didn't work. @jfntn, did you ever get this working?
#2021-03-1715:00borkdudethat config should work though#2021-03-1715:00borkdudeunless you are using a very old version of clj-kondo#2021-03-1715:00Alex WhittI'm on clj-kondo v2021.02.13#2021-03-1715:02borkdudeI'll try#2021-03-1715:03Alex WhittMuch obliged, thank you#2021-03-1715:04Alex WhittI'm on Spacemacs and I have the correct config AFAICT. It's still giving me "unresolved symbol."#2021-03-1715:05borkdude@alex.joseph.whitt def-catch-all, not def-catch-call#2021-03-1715:07Alex WhittThat was it! That'll teach me to copy-paste without double checking#2021-03-1715:11Alex Whitt@borkdude, is it still expected that references to the defn-spec'd function would show "Unresolved var" warnings? Or should that work too?#2021-03-1715:12borkdudeLet me try...#2021-03-1715:13borkdudeLooks like it works correctly here:#2021-03-1715:14borkdudeYou will need to re-visit your other buffer though in order for the cache to pick up your new vars#2021-03-1715:14borkdudewith your new config#2021-03-1715:16Alex WhittMight it make a difference that the var is in a local dependency lib through :local/root?#2021-03-1715:17Alex WhittOddly it only shows up on one reference in the file, while other references to the same var don't complain#2021-03-1715:18borkdudetry clj-kondo --lint $(clojure -Spath) --parallel --no-warnings#2021-03-1715:18borkdudethat will lint your deps#2021-03-1715:19borkdudeand put the var info in your local cache#2021-03-1715:19Alex Whitt🙏#2021-03-1715:19borkdudeif you edit a local/root dep, that info doesn't end up in your project's cache, but in the other project's cache#2021-03-1715:19Alex WhittThank you!#2021-03-1715:19Alex WhittSo I would have to re-run that to pick up changes in the dep, then?#2021-03-1715:19borkdudeyes#2021-03-1715:19Alex WhittAlright, understood. I'm glad this all works.#2021-03-1715:20borkdudeyou can also just lint clj-kondo --lint ../../the-other-local-root/whatever to update#2021-03-1715:20borkdudeif you want to sync#2021-03-1716:03ericdallo@borkdude when clj-kondo adds :defined-by key to a var-definition analysis bucket?#2021-03-1716:04ericdalloFor a code like:
(defflow my-flow
   ....)
I want to know if the my-flow is defined-by defflow
#2021-03-1716:04ericdallothis already works with deftest#2021-03-1716:04ericdalloNot sure this is related with defflow being a custom hook#2021-03-1716:04ericdallofor other macros lke defn it doesn't add the defined-by#2021-03-1716:05ericdalloMy issue: I implemented on clojure-lsp the :exclude-when-defined-by on its custom linter https://clojure-lsp.github.io/clojure-lsp/settings/#unused-public-var, but it seems it doesn't work since clj-kondo don't send the defined-by for other symbols than deftest#2021-03-1716:08borkdudeyeah, we can add that. issue + PR welcome#2021-03-1716:08borkdudeit's pretty much ad hoc I think#2021-03-1716:09borkdudethis is used by carve a lot to exclude "unused vars"#2021-03-1716:10ericdalloI see, do you think we would add defined-by key to every var-definition?#2021-03-1716:11borkdudewhat info do you actually want to have: - IF it was defined by something custom? - Or which thing it defined?#2021-03-1716:12ericdallowhich thing it defined, so we could compare with the provided exclude setting from user#2021-03-1716:12ericdalloWe already have that for deftest, I think is just make it work for other macros/functions ?#2021-03-1716:14ericdallohttps://github.com/clj-kondo/clj-kondo/issues/1216#2021-03-1718:28ericdallo@borkdude I started to implement that, is there any way to get the namespace and the symbol of the var on https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/analyzer.clj#L427? I only found call https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/analyzer.clj#L433 that only have the symbol name, not the ns#2021-03-1718:30borkdudecan you post this as a comment on the github issue? I'm losing track of all threads here in Slack...#2021-03-1718:30ericdalloSure!#2021-03-1814:57leoiacoviniHey folks 👋 , @ericdallo and I have been experimenting with hooks recently, and I found some behaviors that were not completely clear to me, and for several folks at work, and wanted to discuss a bit with you if this makes sense: • Apparently, hooks are only copied from the libs classpath when running cl-kondo with the --no-warnings flag, this make editors that uses the clojure-lsp not install the custom hooks when starting up, which is very misleading in a lot of cases • The interaction between project specific .clj-kondodirection and the home one is not very clear, I found that having some custom config.edn per project, makes the hooks declared in the home folder to not work correctly • Download hooks are versionated, and it’s not clear for me if they are re-copied when I bump my lib version. This could be a problem when working with projects that have different hooks definitions depending on the lib version I see that mostly of those problems comes from the strategy to copy the hooks into somewhere else, using a manual process, Ideally I think that would be cool if clj-kondo would be able to fetch the hooks definition from the classpath at runtime (does that make sense?), but probably tis has several complexities that I am not aware#2021-03-1814:59borkdude@leoiacovini - afaik clojure-lsp already uses the --no-warnings flag when initially linting the classpath, so this should work exactly the same. - hooks are supported in the home directory, but hook code is always resolved relative to the config file it was declared it - when hook code is fetched from the classpath it will overwrite current hook code, so updating is automatic#2021-03-1815:05leoiacovini1. :thinking_face: I am pretty sure it isn’t working then, because we got several people at work (including myself) not having it copied when starting the clojure-lsp, cc/ @ericdallo 2. I have observed that If I have .clj-kondo in my project (to override/add project specific configs) the hooks ended up being download inside it (I need to redo some tests about how the configs were, but I remember being a bit lost at the time) 3. Do you think that having it versionated (like ~/.m2) by the library version that exported it makes sense? Or the always override approach should be enough?#2021-03-1815:08borkdude1. clj-kondo only repro welcome 2. same 3. I don't see why this is needed, since the hook code comes from your project dependencies. if you would have different versions of hook code, then your clj-kondo.edn would also have to change.#2021-03-1815:08ericdallo1. We don't use any no-warning flag @U04V15CAJ: https://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/config.clj#L16-L33, should we pass a :no-warnings ? Is this will return the findings and analysis correctly ? #2021-03-1815:10borkdude@ericdallo clj-kondo assumes you are going to lint your dependencies once, to get arity info for those. and in this phase you are not interested in findings, but you are possibly interested in hook code from the deps. this is why :no-warnings has this effect#2021-03-1815:11ericdalloit makes sense, so the first scan when project start make sense to pass the :no-warnings , right?#2021-03-1815:11borkdudeyes, but you won't get any findings then#2021-03-1815:12borkdudeso ideally you would split it into two phases: 1) deps only + no-warnings 2) project sources only (if you need findings for those)#2021-03-1815:13borkdudewe can also make an explicit flag for this maybe, --copy-hooks#2021-03-1815:14ericdalloWe just need the findings when analyzing a single file, so I think passing the :no-warnings https://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/config.clj#L16 would be enough, I'll make some local tests though#2021-03-1815:14borkdudeok cool#2021-03-1815:14ericdalloyeah, a copy-hooks would be util if that doesn't work, I'll let you know, thanks!#2021-03-1815:23ericdalloOh, the :no-warnings don't print the analysis as well, so that will not work for clojure-lsp, @U04V15CAJ do you think it makes sense to change the check to copy hooks to check for a --copy-hooks instead checking no-warnings ?#2021-03-1815:24borkdudeYes#2021-03-1815:51ericdalloabout 1: https://github.com/clj-kondo/clj-kondo/pull/1221#2021-03-1815:53borkdudeLooks ok. > The --copy-hooks flag is used to indicate that clj-kondo is used to populate the cache. This doc needs to change to: indicate that hook code should be copied from dependencies. Also, undocument the no-warnings flag, we will keep supporting it as it is now, but I want to get rid of it altogether from the public API#2021-03-1815:54borkdudesince the name is confusing#2021-03-1816:08ericdalloDone!#2021-03-1818:33ericdallo@leoiacovini 1. fixed on clojure-lsp, next releases should fix that issue 2. Maybe we can improve docs to make that easier to understand? still think a repro would help find if there is a bug#2021-03-1818:42borkdude@ericdallo I'm working on renaming the option to --copy-configs
#2021-03-1818:43borkdudeit doesn't only copy hooks#2021-03-1818:43borkdudedone#2021-03-1818:47ericdalloit makes sense#2021-03-1911:25Volodymyr HuzarHello! I am getting an :unused-private-var error for the code below:
(deftype ^:private SessionStore
         [session-service] ...)

(defn db-store [this]
  (SessionStore. this))
Is it something wrong with code on linter is false positive in this case?
#2021-03-1911:27borkdudeabout the function db-store?#2021-03-1911:28borkdudeI can't infer from your snippet that this function is used anywhere or not#2021-03-1911:29Volodymyr Huzarsorry, corrected the example, about ns.some/->SessionStore#2021-03-1911:31borkdudeThis is a false positive. Feel free to post an issue#2021-03-1915:55Volodymyr HuzarBug is created https://github.com/clj-kondo/clj-kondo/issues/1222#2021-03-1911:31borkdudeI think clj-kondo never encountered a private deftype before#2021-03-1912:37yuhanwould it make sense for clj-kondo to resolve ns aliases in syntax-quoted forms?#2021-03-1912:37yuhaneg. this compiles even though there's no str alias in the namespace
(defmacro m [coll]
  `(str/join ~(conj coll "hello")))
#2021-03-1912:39yuhanwhen called from another namespace, it expands to the literal symbol str/join which is unresolved#2021-03-1912:42borkdudeI think that makes sense, but how can clj-kondo know str is not a fully qualified namespace in general - heuristics?#2021-03-1912:42borkdudeI think single segment is probably a safe heuristic#2021-03-1912:44yuhanYeah, that was what I thought - or anything that's not explicitly :required by the namespace?#2021-03-1912:45borkdudeok, so warning: "Missing alias: str" maybe then? yeah#2021-03-1912:45borkdudeI think this can work in general. Right now clj-kondo warns about "Unresolved namespace str" , but I think we could also change that to "Unresolved alias" instead in case of single segment#2021-03-1912:45yuhanI can imagine a strange unhygenic macro which behaves differently according to the aliases of the ns which calls it#2021-03-1912:46yuhanbut that's probably very discouraged#2021-03-1912:47borkdudeyeah, in that case you can use #_:clj-kondo/ignore#2021-03-1913:05yuhanThe bug I ran into actually involved a multi-segment alias (`c2d.c` for clojure2d.color) but I think that's a reasonable heuristic#2021-03-1913:05yuhaneg. a macro-defining ns might want to use fully qualified vars without requiring the ns in advance#2021-03-1913:06borkdudehmm, so this would still not have been caught for you right#2021-03-1913:06yuhanyeah#2021-03-1913:08yuhanRight now clj-kondo lets you use fully-qualified vars anywhere even though that might lead to subtle breakages with ns loading order - was that an explicit decision?#2021-03-1913:08borkdudeCan you give an example?#2021-03-1913:11yuhaneg namespace A requires B and C, B requires D C refers to D/foo without explicitly requiring it, this works because D has been loaded in advance. Later on B drops the D requirement, causing A to break the next time you load it in a repl#2021-03-1913:13yuhan(I've encountered this several times due to long-running repl sessions and shuffling namespaces around)#2021-03-1913:14borkdudeclj-kondo warns about namespaces that you have not explicitly required#2021-03-1913:14borkdudee.g. when you type (clojure.string/join [:foo :bar]) without a require, you get a warning#2021-03-1913:16yuhanoh..:face_palm: for some reason I didn't see that warning, might have been editor lag#2021-03-1913:17yuhancould it just extend that analysis into syntax-quoted positions then?#2021-03-1913:19borkdudeI don't think that would be correct, since the namespace defining the macro isn't always the one who should require the namespace used in the macro expansion#2021-03-1913:19borkdudealthough in 99% of the cases, maybe it should#2021-03-1913:20yuhanhmm yeah, I wonder how often that happens in the wild#2021-03-1913:21borkdudewe can implement it as an optional linter and then see how much false positives we get#2021-03-1913:21yuhanprobably where a utility namespace is defining macros and would otherwise lead to circular requires#2021-03-1913:21yuhanalright, should I open a GH issue?#2021-03-1913:22borkdudeyeah#2021-03-1919:02tanzoniteblackis there a way to have clj-kondo print out the fully merged config it’s made? Trying to debug why my malli generated extra configs aren’t working & want to make sure they’re even being included#2021-03-1919:05borkdude@tanzoniteblack you can view this from the REPL, when you invoke (clj-kondo.core/run! {:lint ["src"]}), the return value will give you a map with :config in it#2021-03-1919:14tanzoniteblackhm…as far as I can tell this is correct, but the linter in the malli directory doesn’t actually seem to be running
:config {:config-paths ["configs/malli"],
          :linters {:type-mismatch {:level :error},
                    :format {:level :warning},
                    :redundant-let {:level :warning},
                    :misplaced-docstring {:level :warning},
                    :missing-test-assertion {:level :warning},
                    :duplicate-set-key {:level :error},
                    :duplicate-map-key {:level :error},
                    :missing-clause-in-try {:level :warning},
                    :inline-def {:level :warning},
                    :missing-body-in-when {:level :warning},
                    :missing-docstring {:level :off},
                    :conflicting-alias {:level :error},
                    :unused-import {:level :warning},
                    :unbound-destructuring-default {:level :warning},
                    :syntax {:level :error},
                    :unused-namespace {:level :warning, :exclude ["taoensso.timbre"]},
                    :not-a-function {:level :error, :skip-args [korma.core/aggregate]},
                    :unresolved-namespace {:level :error},
                    :invalid-arity {:level :error,
                                    :skip-args [yummly.util.korma-util/defentity-tagged
                                                korma.core/defentity
                                                yummly.mobile-util.moustache/app
                                                korma.core/select
                                                korma.core/update
                                                korma.core/delete]},
                    :constant-test-assertion {:level :warning},
                    :missing-map-value {:level :error},
                    :unreachable-code {:level :warning},
                    :redefined-var {:level :warning},
                    :unused-binding {:level :off}},
          :lint-as {taoensso.timbre/debugf clojure.tools.logging/debugf,
                    taoensso.timbre/infof clojure.tools.logging/infof,
                    taoensso.timbre/warnf clojure.tools.logging/warnf,
                    taoensso.timbre/errorf clojure.tools.logging/errorf,
                    clojure.core.async/go-loop clojure.core/loop,
                    potemkin/defrecord+ clojure.core/defrecord},
          :output {:exclude-files ["./test/yummly/util/tracing.clj"]},
          :cfg-dir "/Users/ryan/Code/api/.clj-kondo"},
#2021-03-1919:14tanzoniteblack
~/Code/api(introduce-malli:zap:)» cat .clj-kondo/configs/malli/config.edn -p
{:lint-as #:malli.schema{defn schema.core/defn}, :linters {:type-mismatch {:namespaces {yummly.data.recipe-collection {get-sort-by-order-hugsql {:arities {1 {:args [:string], :ret :string}}}}}}}}
#2021-03-1919:15borkdudeif things are merged correctly, you should see the malli config in that returned config#2021-03-1919:15tanzoniteblackoh. and I don’t#2021-03-1919:15tanzoniteblackgotcha, this is what I needed to debug 🙂#2021-03-1919:16borkdudewhat version of clj-kondo is this?#2021-03-1919:16tanzoniteblack:config-paths ["configs/malli"] at the top level does imply that I have a directory called .clj-kondo/configs/malli#2021-03-1919:16tanzoniteblackright?#2021-03-1919:16tanzoniteblack"2021.03.03"#2021-03-1919:16borkdudecorrect#2021-03-1919:31tanzoniteblackfigured it out. I’m using a custom config .clj-kondo/config-ci.edn; but it looks like :config-paths only gets picked up if .clj-kondo/config.edn exists & specifies the key#2021-03-1919:31tanzoniteblackhttps://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/core.clj#L121#2021-03-1919:32tanzoniteblackso if I do
(clj-kondo.core/run! {:lint ["src"]
                      :config "/Users/ryan/Code/api/.clj-kondo/config-ci.edn"})
with :config-paths in it, they don’t get picked up
#2021-03-1919:33tanzoniteblackif we specify custom config paths, is there a reason we shouldn’t resolve and merge in this specified in :config-paths? I can probably make a PR today or next week to handle that situation if you think it’s the right behavior#2021-03-1919:34borkdudeCan you lay this out step by step in an issue? I'm kind of swamped in all kinds of slack threads#2021-03-1919:37tanzoniteblackUnderstood.#2021-03-1919:38borkdudeI think you're on to something and it probably should be fixed, but github issue is best with some kind of small repro#2021-03-1919:40tanzoniteblackLunch and bunch of meetings first, then I'll make an issue for it#2021-03-2009:06borkdudeToday it's clj-kondo's 2nd birthday!#2021-03-2018:18lread@borkdude I am using clj-kondo with joy as a library in test-doc-blocks. I am parsing docstrings for markdown code blocks to convert to tests. My brain was getting a sprain when dealing with kondo analysis for :doc and I suspect that https://github.com/clj-kondo/clj-kondo/blob/374094a1776878ec4b5079869e7f13e3f7c1ad20/src/clj_kondo/impl/utils.clj#L161 correctly. For example if I have a docstring "A little function went to the \"store\" kondo :doc is giving me "A little function went to the \\\"store\\\"" .#2021-03-2018:29borkdude@lee Issue + fix welcome!#2021-03-2018:35lreadwill do sometime today#2021-03-2119:33seancorfieldJust noticed this issue:
Can't parse /Developer/workspace/clj-new/src/clj/new/app/deps.edn, No value supplied for key: namespace clj-kondo (syntax)
for this deps.edn file (which is a template in clj-new):
{:paths ["src" "resources"]
 :deps {org.clojure/clojure {:mvn/version "1.10.3"}}
 :aliases
 {:run-m {:main-opts ["-m" "{{namespace}}"]}
  :run-x {:ns-default {{namespace}} ; complaining about this
          :exec-fn greet
          :exec-args {:name "Clojure"}}
...
This is a Stencil template (but Selmer and others use the same syntax). Not sure if it’s possible to work around this since it’s a parsing issue at the EDN level but I thought I’d mention it in case…
#2021-03-2119:45borkdude@seancorfield If the file ends with .edn, clj-kondo will treat it as edn#2021-03-2119:45borkdudeyou can exclude the file in your config#2021-03-2119:47seancorfieldRight, I meant more “Could clj-kondo understand that {{sym}} is a template var and still parse the file?“.#2021-03-2119:47seancorfieldAlso, while you’re here — I just ran across this:
(ns kondo.reducers
  (:require [clojure.core.reducers :as r]))

(defn map-test []
  (r/map inc [1 2 3 4]))
  ;^ r/map flagged as an unresolved var
#2021-03-2119:47borkdudethat would require a change in the parser, which imo isn't worth it. the r/map issue will be fixed in the newest clj-kondo which I'm about to release#2021-03-2119:48seancorfieldOh, good timing on my part then 🙂#2021-03-2119:49seancorfieldYeah, I figured it wouldn’t be worth fixing the EDN parse issue. I was just curious if anyone else had run into it.#2021-03-2119:49borkdudeI have run into it myself :)#2021-03-2119:50borkdudeit's unfortunate that {{ ... }} is invalid EDN in this case#2021-03-2119:52borkdudeif only we had some HEREDOC feature in clojure :P (j/k)#2021-03-2119:53seancorfield(which wouldn’t solve that parsing issue but… 🙂 )#2021-03-2120:41borkdudeI just had a pain with lein updating the clj-kondo LSP plugin. Turns out I had clj-kondo in my .lein/profiles.clj as well, so it had included an older version for a while.
lein with-profiles -user
fixes this.. facepalm
#2021-03-2120:46borkdudeWell, here it is then:#2021-03-2120:46borkdudeclj-kondo v2021.03.22: no new features, just bug fixes. https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#20210322#2021-03-2122:05borkdude@seancorfield I guess a quick hack for templates would be to str/replace all {{ ... }}s with e.g. nil and then lint it as .edn. But how would you tell clj-kondo that it should do that.#2021-03-2216:02richiardiandreaHi there, say I have with-db-transaction called this way jdbc/with-db-transaction [tx (:spec db) {:isolation :repeatable-read}] - how would I go in linting it so that it detects the last option map?#2021-03-2216:06richiardiandreaI see this PR here https://github.com/clj-kondo/clj-kondo/pull/823/files I am checking if I can use it as well (using clojure.java.jdbc)#2021-03-2216:10richiardiandreaok never mind, it turns out I had a {clojure.java.jdbc/with-db-transaction clojure.core/let} and the above is built in so I just removed it#2021-03-2216:13borkdudeDoes the current implementation of these macro analyzers not cover all usages?#2021-03-2216:17richiardiandreait does - see my above answer, I had miss-configured my config.edn#2021-03-2216:17richiardiandreathanks for checking in 😉#2021-03-2217:13heliosIn this blogpost about our bootstrapped CI i show how we directly tap into Clj-kondo from a notebook for our CI linting https://nextjournal.com/blog/ci#2021-03-2217:19borkdude@helios Nice incremental approach. > This is not something that couldn't have been achieved with a traditional CI and a bit of Bash scripting Since you are bringing up bash: also possible using babashka and the clj-kondo pod btw hehe#2021-03-2217:20borkdudeBut if you are running a JVM for testing anyway, yeah, why not run clj-kondo as part of it :)#2021-03-2217:35borkdude@helios Maybe worth adding a link in ci-integration.md about this article#2021-03-2410:14robert-stuttaford<snip>#2021-03-2410:27borkdude@robert-stuttaford Please move the question as a Q/A here: https://github.com/borkdude/edamame/discussions/categories/q-a We can continue the discussion over there, as this doesn't really belong in this channel#2021-03-2410:50robert-stuttafordthank you! https://github.com/borkdude/edamame/discussions/80#2021-03-2420:43snoeit seems kondo does some sort of deduplication of findings. is there a way to output findings for the duplicates?
$ printf "foo\nfoo" | clj-kondo --lint -
<stdin>:1:1: error: unresolved symbol foo
linting took 35ms, errors: 1, warnings: 0
#2021-03-2420:45borkdude@snoe clj-kondo only outputs the first unresolved symbol as to not flood users with the same type of warning#2021-03-2420:45borkdudethis also ties into #_:clj-kondo/ignore: ignoring the first one, ignores all the next unresolved symbols of the same name#2021-03-2420:46snoeis it possible to turn that off? it's really annoying in the editor to play whack a mole, fixing the first and having the second pop up.#2021-03-2420:46snoemakes a lot of sense from the command line, but maybe the count of 1 error is misleading in the same way (with a flag obvs)#2021-03-2420:48borkdudeIt's currently not possible. I have discussed this with @ericdallo before as well and I suggested making an option for this in the unresolved-symbol linter#2021-03-2420:48snoegotcha, sorry must have missed it. Is it only that linter that ignores?#2021-03-2420:49borkdudeno, but the ignore is applied to a later phase then where the unresolved findings are emitted, so when you ignore the first one, the other part of the code still thinks there is one, let's say#2021-03-2420:50borkdudelet me point you to the code#2021-03-2420:50borkdudesorry, gotta go for a half an hour first#2021-03-2420:53borkdudeso what happens: https://github.com/clj-kondo/clj-kondo/blob/76143d350946c18cd3ffc425b35aa01a6c78561d/src/clj_kondo/impl/namespace.clj#L267 unresolved symbols are kept in a map. when there is already one in the map, it is not overwritten (as to not generate multiple) I copied this behavior from joker and personally I liked it but I'm open to optionally change it#2021-03-2420:53borkdude(now afk for a bit)#2021-03-2420:59borkdudewe could e.g. change the map values to vectors#2021-03-2420:59borkdudeand by default only report the first one#2021-03-2421:00snoewould you like to keep the overwriting from a perf perspective?#2021-03-2421:07snoeAnother question, where would you like the config flag? {:skip-duplicates true} alongside skip-args feels right but it seems like only unresolved-vars and unresolved-symbols has this property so it might feel inconsistent.#2021-03-2421:19borkdudeI think the option should go into each linter separately. I think also unresolved-namespace has it. I think it should be something like :report-duplicates true so not having this property defaults to nil#2021-03-2421:20borkdudewhat do you mean from a perf perspective?#2021-03-2421:22snoeI guess there could potentially be a large vector underlying the linter, if report-duplicates is false, it might make more garbage than you're comfortable with.#2021-03-2421:22snoeI'm thinking to your comments about destructuring and such#2021-03-2421:54borkdudeAh, right. I think unresolved-symbols are the unhappy path, there should be relatively few of them, so I think that would be ok#2021-03-2503:48snoethanks hopefully the pr is close#2021-03-2503:49snoei looked at the code for unused-namespace and it doesn't seem like it's deduping, but I could have missed something.#2021-03-2507:49borkdudeUnresolved namespace #2021-03-2503:49snoeTwo more questions: would it be possible to add #_ handling to skip-comments or, rather, where should I add similar behaviour? This is biting me all the time, when I have temporarily ignored code and try to get the signature of a function and come up empty because there's no analysis for the form.#2021-03-2503:53snoeFor keyword def analysis (and I admit I might be too late to this convo) in the old version of lsp, it was nice to mark a re-frame keyword as a definition and get the signature of the associated function. So (rf/reg-sub ::foobar (fn [db [_ foobar]] ...)) would allow you to hover on ::foobar elsewhere in the code and see the [db [_ foobar]] signature. I've been missing this more and more lately, and it would be nice if analysis could provide it.#2021-03-2512:55borkdude@snoe question 1: not sure what you mean, sorry. Can you post the idea here? https://github.com/clj-kondo/clj-kondo/discussions/categories/ideas with more explanation? It's easier for me to track than Slack discussions when it's a longer idea question 2: I think we should just add built-in support for re-frame to get the right definition, since it's such a common library#2021-03-2515:02snoe1. will do. 2. there are other libraries like kee-frame that would need similar. So re-frame makes sense to be build in but there's probably needs to be more to the hooks api and a place to add signatures to keyword analysis.#2021-03-2515:34borkdude@snoe don't we already have this function, reg-keyword-def or something?#2021-03-2515:35snoeyup, but no way to associate a signature#2021-03-2515:37borkdudeCan you make a separate discussion for this on Github at https://github.com/clj-kondo/clj-kondo/discussions/categories/ideas?#2021-03-2809:40borkdude#2021-03-3121:42borkdudeclj-kondo 2021.3.31: minor bugfix release with one new feature by @snoe: - add config to see all occurrences of an unresolved symbol/namespace/var with the same name (by default only the first is shown) https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#2021-04-0107:57michalhey, I believe it was asked hundreds times here, but I'm still unable to find a solution - unresolved vars when linting a code with hugsql generated functions. in general all the calls like db/find-user-by-id are ignored (as the documentation says) but only as long as I do not re-evaluate the db namespace again (which auto re-generates functions). then, to get rid of clj-kondo warnings I need to clear the .clj-kondo/.cache and the linter is happy again. well... till next evalutation, which happens quite often as that's the way of refreshing hugsql functions after changes made in SQL queries.#2021-04-0107:57michalis there anyway of making clj-kondo aware of the namespace evaluation and force it to clean its cache?#2021-04-0108:32borkdude@michal you can ignore the vars in db by adding it to {:linters {:unresolved-var {:exclude [db]}}}#2021-04-0109:03michalawesome, namespace exclusion does its job. thanks!#2021-04-0108:32borkdudeI think you should not see unresolved vars in a hugsql namespace if there are no other user defined functions in the source though#2021-04-0108:33borkdudethe way I am using hugsql is to make special foo.db.hugsql namespaces where only the vars from hugsql are defined and I call those from foo.db#2021-04-0113:28delaguardowarning: Unresolved var: async/<!! I start getting this warning recently, probably because in clojure.core.async <!! is not a defn or macro anymore. it is defblockingop now - https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L125-L136#2021-04-0114:43borkdudeFeel free to post an issue. For now you can fix this in your config with :lint-as#2021-04-0209:18borkdude@U04V4KLKC fixed: https://github.com/clj-kondo/clj-kondo/issues/1244#2021-04-0113:35souenzzoNot sure how to report, but a lint idea: https://gist.github.com/souenzzo/5620ef8587b5e9735808c113e01eab6d#2021-04-0113:41delaguardothis one is tricky because you might want to have deliberately two different implementations for the same dispatch value. For instance - in two separate namespaces#2021-04-0113:44souenzzoit isn't a anti-pattern? can be an "disabled by default" lint?#2021-04-0113:46delaguardosure it can be disabled by default#2021-04-0113:48delaguardoI found it useful in combination with integrant and “multi-artifact project” (one source distributed as a multiple slightly differently configured jars)#2021-04-0114:42borkdudealready logged, feel free to give feedback there: https://github.com/clj-kondo/clj-kondo/issues/1061#2021-04-0114:21pinkfrogCan clj-kondo update source file?#2021-04-0114:41borkdudeClj-kondo does not update your code. You might want to look at clojure-lsp for this.#2021-04-0114:41borkdudeIt uses clj-kondo and then actions on its findings.#2021-04-0114:55pinkfrogclojure-lsp? seems a similar product of cider#2021-04-0114:56borkdudeit can do more than cider though in terms of rewriting your code. what kind of stuff would you like to "update"?#2021-04-0115:06pinkfrogsome unused imports#2021-04-0115:11borkdude@UKFSJSM38#2021-04-0115:13ericdalloHey @UGC0NEP4Y, check https://clojure-lsp.github.io/clojure-lsp/features/ and https://emacs-lsp.github.io/lsp-mode/tutorials/clojure-guide/, if any questions you can ask on #lsp#2021-04-0115:14pinkfrogThanks.#2021-04-0220:23vemvrefactor-nrepl can do this. That specific functionality doesn't actually use much nrepl or tools.analyzer stuff iirc - I think it's more lightweight. I've been thinking of creating a "spin-off" of refactor-nrepl just for that - otherwise it's bit of a delicate dependency to ask people to have#2021-04-0219:48seancorfieldI’m seeing warnings about “unused default for binding <sym>” for destructured argument bindings that absolutely are used in the function body that follows. Is this a known issue and/or recently fixed?#2021-04-0219:49borkdudenot known to me#2021-04-0219:51seancorfieldSharing work code via DM.#2021-04-0222:04cjsauerI’m having some trouble with Unresolved symbol errors happening inside of custom macros that are themselves inside of reader conditional forms. I have the following set in my config.edn file:
{:lint-as {mount.core/defstate                                      clojure.core/def
           taoensso.encore/if-let                                   clojure.core/let
           com.wsscode.pathom.connect/defresolver                   clojure.core/defn
           com.fulcrologic.fulcro.components/defsc                  clojure.core/defn
           com.fulcrologic.fulcro.routing.dynamic-routing/defrouter clojure.core/defn
           com.fulcrologic.fulcro.mutations/defmutation             clojure.core/defn
           com.fulcrologic.guardrails.core/>defn                    clojure.core/defn
           com.fulcrologic.rad.attributes/defattr                   clojure.core/def}
 :linters
 {:unresolved-symbol
  {:exclude
   [(com.fulcrologic.fulcro.mutations/defmutation)]}}}
#2021-04-0222:04cjsauerI thought the exclusion above would solve it, and it solved some of them, but I’m still seeing params linted incorrectly (see image)#2021-04-0222:05borkdudeyou are using lint-as and unresolved-symbol config for the same macro#2021-04-0222:05borkdudeI'm not sure if that works#2021-04-0222:06borkdudetry {:lint-as {com.fulcrologic.fulcro.mutations/defmutation clj-kondo.lint-as/def-catch-all} and remove the :exclude#2021-04-0222:07cjsauerAh! That worked, but only for the forms inside of the #?(:cljs …) forms…the ones inside of #?(:clj …) are still showing the same unresolved symbol error :thinking_face:#2021-04-0222:08cjsauerSomething with the reader conditionals is confusing kondo. I see a whole bunch of “unused namespace” warnings too, but those are clearly used by the :cljs forms#2021-04-0222:09borkdude@cjsauer if only the :cljs branch is using those namespaces, you should put the :require of that namespace in a :cljs branch too, else clj-kondo will tell you it's unused (namely in the JVM invocation of that .cljc file)#2021-04-0222:10borkdudethe model that clj-kondo uses for linting .cljc files is: 1) lint once for .clj, reading everything but not .cljs branches 2) lint once for .cljs, reading everything, but not .clj branches#2021-04-0222:12borkdudeI'll be afk now, it's getting late. Feel free to post an issue if nobody else helps you out in the coming few hours.#2021-04-0222:14cjsauerThat solved the unused namespace warnings! No prob, thank you @borkdude#2021-04-0222:25cjsauerActually, using the :lint-as and unresolved-symbol configurations together does almost seem to work. That removes all errors, except the unresolved symbols defined by the macros themselves.#2021-04-0222:25cjsauer#2021-04-0222:28cjsauer#2021-04-0222:28cjsauerAh there we go! Here is the config that ended up working ☝️#2021-04-0222:29cjsauer> you are using lint-as and unresolved-symbol config for the same macro This seems to work just fine…although maybe that’s just a happy accident..#2021-04-0320:50ericdalloAny reason why clj-kondo doesn't lint (Foo.) as unresolved-symbol but it does when Foo. without the parens? 🧵#2021-04-0320:50ericdallo#2021-04-0320:52borkdudeThe second one might be a constructor call for a class that's available#2021-04-0320:53ericdallobut the class is not imported, shouldn't lint as something like that?#2021-04-0320:54borkdudeyou don't have to import a class to be able to use it#2021-04-0320:55ericdalloI didn't know about it, besides java.lang is there other classes that one can configure to use without import?#2021-04-0320:55borkdudeyou can use any class without importing it by using the classname#2021-04-0320:56borkdudeand in this case Foo is a single segment class name#2021-04-0320:56ericdalloOh yeah, it makes sense, you mean java.util.Date would be valid right?#2021-04-0320:56borkdudeThe check for class names used to include a dot, but I lifted this since some people did have single segment classes#2021-04-0320:56borkdudeyes#2021-04-0320:57ericdalloI see, that's what I was about to suggest#2021-04-0320:57borkdudeyou can probably find a unit test that explicitly supports this#2021-04-0320:57borkdudeand some issue number#2021-04-0320:57ericdallohahah no problem, I can see now why don 't restrict that#2021-04-0320:58borkdudedarn, now I'm curious myself what the issue number was ;)#2021-04-0320:59ericdallohahahaha sorry#2021-04-0321:01borkdudeI can find one here: https://github.com/clj-kondo/clj-kondo/issues/950 but that doesn't have this example#2021-04-0321:01borkdudethat was just relaxing foo.bar.Baz to foo.Baz#2021-04-0321:02borkdudethere might be some rule in clj-kondo that says: if the call ends with a dot, just leave it alone, since it's a constructor and people know what they are doing with classes#2021-04-0321:02ericdalloyeah, I see, It would be really cool to find some way to lint that, but I can't think in anything that would always work/makes sense#2021-04-0321:02borkdudeif Foo was a record or deftype you would probably use ->Foo instead#2021-04-0321:09borkdudeMaybe try adding a warning for a constructor call that only has a single segment and see if this breaks any tests#2021-04-0321:10borkdudeIt could be that clj-kondo is just too relaxed for this case#2021-04-0321:11ericdallohum, it would be nice#2021-04-0321:08ericdalloWould be hard to make clj-kondo support java classes arglists/docs in analysis output? 🧵#2021-04-0321:08ericdalloI think would be necessary to add support for java classes analysis that probably is no easy task#2021-04-0321:09ericdalloI mean, I'd like to get a docs or signature of a java class via clojure-lsp#2021-04-0321:10ericdalloATM, java usages are just var-usages buckets, it'd be necessary to have a var-definition for those I think#2021-04-0321:10borkdudeclj-kondo doesn't analyze Java source code#2021-04-0321:11borkdudebut you could maybe retrieve those using reflection and put them somewhere#2021-04-0321:12borkdudecurrently clj-kondo uses some javadoc stuff to store all this info#2021-04-0321:12borkdudebut reflection might have been a better choice, easier#2021-04-0321:12ericdalloyou mean clojure.java.javadoc?#2021-04-0321:13borkdudeno, the javadoc command#2021-04-0321:14borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/extract/clj_kondo/impl/ExtractJava.clj#2021-04-0321:15borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/script/extract-java#2021-04-0516:19cjsauerWhen writing a custom hook, can I pass line/col metadata in the ex-data of an error?#2021-04-0516:19cjsauerI want to treat this problem as an error, not a warning, but still retain helpful line/col info#2021-04-0516:20cjsauerRight now when I throw, it “puts” the error onto the top-level form, but I have the exact line/col info of the real issue#2021-04-0516:20cjsauer
(throw (ex-info "defmutation handlers must take 1 argument"
                          {:type :fulcro/defmutation
                           :row row
                           :col col}))
#2021-04-0516:20cjsauerSomething like this#2021-04-0516:20borkdudeyes, that should work#2021-04-0516:21borkdudewell, type isn't picked up from ex-data, but row and col are#2021-04-0516:22borkdudeit probably should, but it isn't the case right now. but you can use reg-finding! to do what you want#2021-04-0516:22cjsauerCan reg-finding! be configured to be a fatal error?#2021-04-0516:22borkdudeyou have to set :level :error#2021-04-0516:22cjsauerAhh duh, I see it now#2021-04-0516:22cjsauerThank you#2021-04-0516:24borkdudenote that the user will also have to configure :fulcro/defmutation in the linter config and set a level for it#2021-04-0516:24borkdudeI think the :level isn't even relevant from where it's emitted, it's always the one from the config#2021-04-0516:25cjsauerHm yea, must be, still can’t quite get it working#2021-04-0516:28cjsauerI think I’m doing something slightly weird is the problem. Basically, I’m transforming fulcro’s defmutation into something like this:
(defn my-mutation
  [params]
  (letfn [(action [env])
          (remote [env])]
    (action nil)
    (remote nil)))
It’s “close enough” to what I want the linting to do, but it’s giving me stray errors like “action is called with 1 arg instead of 0"…I’m trying to override those subsequent/general linters with my own very specific error messages, if that makes sense
#2021-04-0516:35borkdudeI don't know these macros to say with confidence if that makes sense.#2021-04-0516:36borkdudebut in general I think it does#2021-04-0519:30cjsauerInside of a reg-finding! map, how should I qualify :type keywords? I’m thinking something like this: :clj-kondo.fulcro.defmutation/handler-arity#2021-04-0519:31cjsauerOriginally I had :com.fulcrologic.fulcro.mutations.defmutation/handler-arity, but that’s not a domain I own, so I shouldn’t be adding keys to it yea? Still figuring out how to namespace keywords generally…#2021-04-0519:36borkdudeyeah, I think your proposal is reasonable#2021-04-0614:04aptHey folks. Just checking if I’m not missing anything – is there any linter rule for avoiding thread macro abuse? That is, catching things like (-> foo :bar) (should be (:bar foo) or (-> foo :bar :baz) (prefer (get-in foo [:bar :baz]) )#2021-04-0614:06tvaughanNot clj-kondo, but fyi nonetheless https://github.com/jonase/kibit#2021-04-0614:08cjsauerI have a love-hate relationship with kibit. It has a couple helpful linters in it, but it’s really slow, and doesn’t support a lot of cljs syntax (which is what I work in most often). I imagine adding a linter to kondo that detects this issue would be really simple. Looking to see where this would go in the source code…#2021-04-0615:13borkdude
(-> foo :bar :baz) vs (prefer (get-in foo [:bar :baz]) )
can't say that I would endorse this, since the -> variant is often faster
#2021-04-0615:13borkdudeand it's pretty idiomatic as well#2021-04-0615:32cjsauerYea, I actually end up disagreeing with kibit on that exact case. Still, I think the trivial case of (-> foo :bar) is safe to prefer (:bar foo). So the linter would check if you’re using -> with only 2 args, and nothing fancier.#2021-04-0615:33aptYeap, I think we can all agree on that one.#2021-04-0717:27cjsauerhttps://github.com/roterski/fulcro-rad-crux/blob/6baba4fcdf710ed801938067a1b5fe95ee39f8d6/src/main/roterski/fulcro/rad/database_adapters/crux/wrap_crux_save.clj#L103-L116 might change my mind on this linter. Sometimes it really is more readable to use a threading maco with only 2 args, like in the case of a reduce with a large reducing function.#2021-04-0706:46Yehonathan SharvitSometimes, I need to require a namespace for its side-effects (e.g. defmethod declarations). clj-kondo seems to understand that when I write
(ns foo
  (:require bar))
But cider-refactor removes bar from the require list, as it “Remove any unused libspec vectors”. Does anyone know a way to tell clj-refactor to keep bar?
#2021-04-0707:40borkdudeDon’t know, maybe ask in CIDER? Perhaps it can use the same convention as clj-kondo?#2021-04-0707:42Yehonathan SharvitHow did you solve it in clj-kondo?#2021-04-0707:43borkdudeLibraries without an alias or :refer are considered to be required for side effects and left alone #2021-04-0715:08seancorfieldIs there any difference — to the tooling — between (:require bar) and (:require [bar])? I think some tools treat the latter as a special case but not the former?#2021-04-0715:17borkdudeto clj-kondo there is no difference I believe#2021-04-0801:54ProctorI did a threading macro for Promises in ClojureScript to make a Promise (.then p fn) chain look like the normal threading operator macro. clj-kondo started giving arity warnings on the functions that are going to be “threaded”, and was wondering if there is a way to hint at the arity fix: e.g.
(=> promise/resolve({})
  (assoc :a 1))
#2021-04-0801:56Proctorand it would give the arity warning on assoc equivalent, when the macro rewrites it to be:
(promise/then (promise/resolve {}) (fn [x] (assoc x : a)))
so it does get the correct arity when the ClojureScript is compiled and run, as it gives the expected results when doing tests
#2021-04-0801:57Proctorwas wondering if there are any hints for the pre-compiled macro form in ClojureScript, or annotations on the macro#2021-04-0801:57Proctorsince the standard threading operators don’t give those warning#2021-04-0801:57Proctorthanks!#2021-04-0802:00Proctor(where promise/then and promise/resolve are function wrappers for (.then p some-fn) to make it safer to call)#2021-04-0807:17borkdude@steven.proctor You can write a custom hook for this macro or just turn off arity warnings in that macro. https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-04-0807:17borkdudeLove your podcast btw!#2021-04-0812:43ProctorThanks, and thanks!!!#2021-04-0814:54ProctorI have never configured clj-kondo before, so a question on general practice: the macro is in a promise library, it is possible to setup the clj-kondo config with that project so that all projects that use the macro get the config, or does that need to be configured in each project that uses it?#2021-04-0814:54borkdude@steven.proctor That is possible. That mechanism is explained here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-04-0814:57Proctoris that for the config.edn, the hooks definition, or both?#2021-04-0814:57borkdudeboth#2021-04-0820:51Proctor@borkdude thanks!!! I think the lint-as config works, since I was basing it off the -> operator, it looks like I can just lint it as that operator#2021-04-0820:52borkdudeah great :)#2021-04-0911:07serioga
(defn f
  {:doc "Docstring"}
  [])
Missing docstring Bug?
#2021-04-0911:09serioga
(meta #'f)
=>
{:arglists ([]),
 :doc "Docstring",
 :name f, ...]}
#2021-04-0915:28tvaughanI'm using flycheck-clj-kondo to run clj-kondo http://v2021.03.in in emacs. Strangely, it seems as though when clj-kondo is run in emacs clj-kondo doesn't read its config.edn and produces numerous warnings. When I run clj-kondo on the command-line (using the same command-line options used by emacs, I think) no warnings are reported, and reports the same warnings seen in emacs when config.edn is deleted. I'm pretty sure my setup is pretty vanilla, but can anyone think of something I may have set incorrectly or forgot to set that could be the cause of this? Thanks#2021-04-0915:34borkdude@tvaughan Are you using a recent version of flycheck-clj-kondo?#2021-04-0915:35borkdudeAnd do you have some kind of repro? I'm using emacs + flycheck as well#2021-04-0915:39tvaughanI'm using straight.el (and a native compilation build of emacs 28 on macos) which, if I understand how straight.el works correctly, should mean I'm running the latest version currently committed to github. I'll setup a reproduction#2021-04-1114:31borkdude@i let's continue here with your question. can you give an example?#2021-04-1114:38pinkfrog
(ns acme.mobile.log
  (:require [clojure.string :as string]
            [taoensso.timbre :as timbre])
  (:require-macros [acme.mobile.log :refer [debug info]]))

;; debug and info are meant to be used by the *external* libraries that import log.

;; clj-kondo complains debug and info are unused.
#2021-04-1114:38borkdudeyou can configure this. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unused-referred-var#2021-04-1114:42pinkfrogCan I do that inline in the acme.mobile.log file.#2021-04-1114:42pinkfroglike #xxx supprese warning#2021-04-1114:43borkdudeyou can also do that inline using #_:clj-kondo/ignore#2021-04-1114:47pinkfroggreat#2021-04-1114:40borkdude#2021-04-1313:40cjsauerThis isn’t any fault of kondo’s, but I’m wondering how others handle this situation: I have a .cljc file that looks like this
(ns my.cljc.file
  (:require #?(:clj [datomic.client.api :as d])
            [my.model.thing :as thing]
            [my.model.account :as account]))

#?(:clj
   (defn some-function
     []
     {::thing/x 42
      ::account/id 123}))
Because of the way kondo lints cljc files (one pass with clj, one pass with cljs) both the my.model.* requires are marked as unused. This is because technically they aren’t used by the cljs side. But, if I were to move my.model.* requires up into the #?(:clj …) conditional, suddenly the ns can no longer be read, and tools.reader will complain about “unresolved keyword alias ::thing/x”. So tools.reader ignores the reader conditionals, and even in cljs, will attempt to read what’s inside of the #?(:clj ..) conditional forms. Has anyone figured out a clever way to solve this dilemma? At the moment I’m just living with a few “unused namespace” warnings, but they start to become very noisy…
#2021-04-1315:49cjsauerOne solution I’ve found is just to fully type out qualified keywords, like :my.model.thing/id. It seems that all the headaches are the fault of the :: keyword sugar. Clojure keeps pushing me into just not using it at all…#2021-04-1320:51yendaIsn't it a tools.reader bug then?#2021-04-1400:28cjsauerI think it is, I remember seeing a ticket for it at some point. #2021-04-1408:34SigveEven though kondo added Core.match support in 2021.02.13 i still get errors on _ and variable binding. Anything i can do about this?
src/language.cljs:52:17: error: Unresolved symbol: _
src/language.cljs:148:66: error: Unresolved symbol: last-type
src/language.cljs:149:74: error: Unresolved symbol: opt
...
#2021-04-1408:34borkdudeWell, the first step would be to provide a valid repro#2021-04-1408:35SigveOk, so kondo should recognise these patterns in theory?#2021-04-1408:36borkdudein depends: I can't see where these errors are coming from by the text you posted#2021-04-1408:40SigveOf course, sorry: around line 52:
(match [word-class source-type (h/import-type ast) last-valid first-failure expr-settings]
               [_ _ _ (_ :guard (partial h/empty-command? command)) _ _] [:command]

               ...)]
around line 148:
(match [word-class (h/empty-word? word) source-type last-valid first-failure expr-settings option-settings]

          ...
          [:option false _ _ _ _ {:inside-paren? true :last-type last-type}]   #{last-type}
          [:option _ _ _ _ _     {:parenopt? true :closed? false :option opt}] #{(h/opt-param-type command (:name opt))}

          ...)]
#2021-04-1413:40Ben SlessHey, I believe I'm missing it in the documentation, but how do I register macros with lint-as in a namespace's metadata?#2021-04-1413:51Ben SlessI think I figured it out, noting it here for posterity: :clj-kondo/config in the ns form takes a quoted map. for it to work the linted-as symbol needs to be fully qualified. Is there anything I missed?#2021-04-1413:55borkdudethis is correct#2021-04-1413:57Ben Sless:thumbsup:#2021-04-1414:06borkdude@sigve.nordgaard I don't get any lint warnings using this:
(require '[clojure.core.match :refer [match]])

(let [command :foo]
  (match []
         [_ _ _ (_ :guard (partial apply command)) _ _] [:command]
         ))
#2021-04-1414:09borkdudeBut you are in .cljs I see. Never tested that case, it seems the libspec is different there:
[cljs.core.match :refer [match]]
I will fix that, but for now you can use {:lint-as {cljs.core.match/match clojure.core.match/match}}
#2021-04-1414:11borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1252#2021-04-1507:22Sigveyes, .cljs was the problem, thanks:)#2021-04-1710:23yuhan
$ echo 'abc/' | clj-kondo --lint -
<stdin>:1:5: error: Invalid symbol: abc/.
linting took 21ms, errors: 1, warnings: 0
Why does the error get reported at column 5 (after the slash) instead of the start of the symbol? It causes a tiny hard-to-see squiggly line in Emacs, but I'm not sure if that's a frontend issue with flycheck-clj-kondo.
#2021-04-1710:24borkdudeNot sure#2021-04-1710:27yuhanok, I'll log an issue if this isn't a design decision. Still a big improvement from the time I last updated, where it would report at the start of the file 🙂#2021-04-1710:28borkdudeit's not a conscious decision I think#2021-04-1712:17borkdude@qythium Thanks for the PR :)#2021-04-1712:18borkdude
$ ./clj-kondo --lint - <<< 'foo/'
<stdin>:1:1: error: Invalid symbol: foo/.
:thumbsup:
#2021-04-1712:24yuhanThanks for all your work on clj-kondo! I still find it amazing how easy it is to go from "huh, why does that squiggly line look weird" to digging out the root cause and fixing it. Yay for open source 🙂#2021-04-2012:12rickmoynihanIs there a shell one-liner to make clj-kondo return a non-zero exit code on errors only?#2021-04-2012:12rickmoynihanuse case is using git rebase --interactive branch --exec "clj-kondo --lint ./src"#2021-04-2012:12borkdude
clj-kondo --lint - <<< '(inc)'; if [ $? -gt 2 ]; then exit 1; else exit 0; fi
#2021-04-2012:13rickmoynihanhehe ok essentially what I was going to write in the script… fair enough 🙂#2021-04-2012:17rickmoynihanhmm ok small issue, running that actually terminates your shell… I guess that’s expected
#2021-04-2012:18rickmoynihanclj-kondo --lint - <<< '(inc 0)'; bash -c "if [ $? -gt 2 ]; then exit 1; else exit 0; fi" ?#2021-04-2012:18borkdudeoh right, I guess this is better then:
clj-kondo --lint - <<< '(inc)'; if [ $? -gt 2 ]; then false; else true; fi
#2021-04-2012:19borkdude^ @rickmoynihan#2021-04-2012:19rickmoynihanyeah that works better#2021-04-2012:19rickmoynihanthanks 🙇#2021-04-2012:23rickmoynihanhmm actually neither of those appear to halt the rebase exec#2021-04-2012:24borkdude@rickmoynihan even shorter:
clj-kondo --lint - <<< '(inc)'; [[ $? -lt 2 ]]
#2021-04-2012:25rickmoynihanagain it doesn’t stop the exec#2021-04-2012:25rickmoynihandoes ; have the right behaviour?#2021-04-2012:30borkdudesorry it should be:
$ clj-kondo --lint - <<< '(inc)'; [[ $? -le 2 ]]
<stdin>:1:1: error: clojure.core/inc is called with 0 args but expects 1
linting took 50ms, errors: 1, warnings: 0
#2021-04-2012:30borkdudethis returns 1 on exit code 3#2021-04-2012:30rickmoynihanyeah was just looking at that#2021-04-2012:31borkdudecompare:
$ clj-kondo --lint - <<< '(inc)'; [[ $? -le 2 ]] && echo "we made it"
<stdin>:1:1: error: clojure.core/inc is called with 0 args but expects 1
linting took 43ms, errors: 1, warnings: 0
with:
$ clj-kondo --lint - <<< '(inc 2)'; [[ $? -le 2 ]] && echo "we made it"
linting took 12ms, errors: 0, warnings: 0
we made it
#2021-04-2012:31rickmoynihanhmmm that still doesn’t seem to work 😕#2021-04-2012:32borkdudeit does work :)#2021-04-2012:32rickmoynihannot when I run like this though:
git rebase --interactive clj-kondo --exec "clj-kondo --lint ./src; [[ $? -le 2 ]]"
#2021-04-2014:55rwstaunerthe issue may have been that $? would interpolate inside double quotes... you'd want single quotes to delay that in this instance#2021-04-2012:33rickmoynihanI’ve dropped a commit in the middle of a bunch that has a deliberate syntax error#2021-04-2012:33rickmoynihanand it doesn’t stop on it :thinking_face:#2021-04-2012:34borkdudeI don't know how bash and git rebase interact but at this point I give up and write babashka#2021-04-2012:43rickmoynihanputting it in a script works fine as you’d expect#2021-04-2012:34rickmoynihan😆#2021-04-2012:35rickmoynihanPerhaps an extra arg to clj-kondo to make all warnings return 0 would be a useful addition?#2021-04-2012:35borkdudeI think so yes#2021-04-2012:36rickmoynihan--allow-warnings or something?#2021-04-2012:37borkdudeplease come up with a couple more alternative names#2021-04-2012:37borkdude--min-level warning --min-level error ?#2021-04-2012:38borkdude--non-zero-on-errors-only (too long)#2021-04-2012:38borkdude--ignore-warnings would be misleading since clj-kondo still prints them#2021-04-2012:39delaguardo--fail-on warning --fail-on error#2021-04-2012:40rickmoynihan--fail-on seems better#2021-04-2012:45borkdudenice#2021-04-2012:45borkdudeok PR welcome#2021-04-2012:46borkdude+ doc#2021-04-2012:46rickmoynihanCool… I’ll maybe create an issue for it first#2021-04-2012:57rickmoynihanok issue here: https://github.com/clj-kondo/clj-kondo/issues/1259#2021-04-2013:01borkdudeI'll ask @bozhidar how rubocop is calling this option#2021-04-2014:19borkdude
bozhidar We have something like this, let me look it up.
[4:15 PM] It's fail-level - 
[4:16 PM] I think that's pretty common across linters.
#2021-04-2122:50rickmoynihanhttps://github.com/clj-kondo/clj-kondo/pull/1261 Let me know if you want any changes#2021-04-2122:31tobiasI love the idea of clj-kondo but I'm having trouble getting it to work with IntelliJ + Cursive. I've installed it according to the editor integration instructions but I'm not seeing any squiggly underlines anything. I know that the linting is working because I set the file watcher to "show console: always" so I can see all the warnings in the console (e.g. /Some/path/core.clj:7:3: warning: Redundant let expression). It's just that the warnings aren't showing up on the code itself. Any ideas on how to fix? I'm using IntelliJ IDEA 2020.1.4 and Cursive 1.10.2-2020.1#2021-04-2210:45dspHi, I have an unusual linter use-case, I'm not sure how to resolve it. I have a pair of macros defined, simplified example:
(defmacro defn-frame-binding
  ([name args body]
   `(defn ~name ~args (do (with-frame-bindings ~body))))
  ([name docstr args body]
   `(defn ~name ~docstr ~args (do (with-frame-bindings ~body)))))

(defmacro with-frame-bindings
  ([body]
   `(with-frame-bindings ~'frame ~body))
  ([frame body]
   `(let [frame# ~frame
          ~'state (:state ~'connection)]
      (
let's say this is in the kondo-test.macro namespace. then in kondo-test.core,
(defn-frame-binding example
  [frame connection]
  (do
    state))
kondo-test.core> (example nil {:state "hello, world!"}) "hello, world!" However, any variables introduced in the with-frame-bindings macro, for e.g. state in this case, are linted as unresolved symbols. I figure I have to do something like:
{:lint-as {kondo-test.macro/defn-frame-binding  clojure.core/defn
           kondo-test.macro/with-frame-bindings clojure.core/let}}
Though, while it works for the custom defn-like macro, bindings set in with-frame-bindings don't appear to be picked up, probably because it doesn't look like a let, but is an anaphoric macro. Any ideas?
#2021-04-2210:48borkdude@dsp First of all, anaphoric macros are bad. :) But you can tell clj-kondo in the unresolved-symbol config to ignore certain symbols within specific functions.#2021-04-2210:48borkdudeCheck out: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#2021-04-2210:49dspI wondered if there was some more generic way to do that, since otherwise it will get quite unwieldy. I use this macro in lots of functions, so will probably be a lot of repeated lines.#2021-04-2210:50dspAlso, why are anaphoric macros bad? I'm using it in the case of a DSL.#2021-04-2210:51dsp
(defn-frame-binding Tauth
  "auth – messages to establish a connection

  size[4] Tauth tag[2] afid[4] uname[s] aname[s]
  size[4] Rauth tag[2] aqid[13]"
  [frame connection]
  (error! "no authentication required"))
within these functions, frame-{fieldname} get predefined and pulled out of the network frame.
#2021-04-2210:52dspMakes it much more convenient, especially if I modify the underlying data type, since I can just modify the macro that pulls them out, separating the concern for anyone using them.#2021-04-2210:53borkdude@dsp I mean, they are bad in the sense that they are a bit magical, but there are trade-offs, I was being a bit blunt.#2021-04-2210:53borkdudeThey have their place.#2021-04-2210:53dspFair. I worry that they will not play well with clj-kondo out-of-the-box.#2021-04-2210:53borkdudeCan you please take a look at the docs? There are good examples for other anaphoric macros and it works quite well.#2021-04-2210:54borkdudee.g. the streams macro introduces a magical where: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-symbol#2021-04-2210:58dspYes, I had looked at that already. However, it seems like I'd have to define it for any function that calls the macro, unless I'm mistaken.#2021-04-2210:59borkdudeyes, you are mistaking :)#2021-04-2210:59borkdudeyou only write it once for streams and then it works everywhere you call the streams macro#2021-04-2211:00borkdudeunless I am mistaking, which is very well possible#2021-04-2211:02dsp
{:linters
  {:unresolved-symbol
   {:exclude [(kondo-test.macro/with-frame-bindings [state])]}}}
With this, (if I have interpreted the docs correctly), I would expect state to no longer be reported as unresolved.
#2021-04-2211:02borkdudewhen you write
(require '[kondo-test.macro :refer [with-frame-bindings]]) 
(with-frame-bindings state)
that should then work without error
#2021-04-2211:03dspYou are correct. It is a spacemacs bug, had to kill all the buffers to get it to update with that.#2021-04-2211:04dspThanks. Saved me from pulling my hair out wondering why it wasn't working. 🙂#2021-04-2211:04borkdude:thumbsup: glad it's working now#2021-04-2211:06dspspacemacs integration seems quite janky, but that is not the fault of the tool. Lots of strange behaviours, but I guess I will investigate that separately. Thanks a lot for the help.#2021-04-2211:06borkdude@jtlocsei An alternative is to try the intellij LSP plugin. Some people have reported it worked better for them than the filewatcher approach#2021-04-2211:09tobiasYup, LSP works great, I tried it after I couldn't get the filewatcher way working. I noticed the clj-kondo docs say "The LSP server does not provide features other than diagnostics." Does that mean that the LSP approach somehow has less functionality than the filewatcher approach?#2021-04-2211:11borkdudeNo, it means that an LSP server usually also provides things like finding references, refactoring etc#2021-04-2211:11borkdudeHaving said that, you might even be able to get clojure-lsp working with the LSP plugin, which does provide a lot more#2021-04-2211:11borkdudeit also uses clj-kondo under the hood so you will get the same diagnostics#2021-04-2211:11borkdudeSee #lsp#2021-04-2211:14borkdudeI have changed the wording a little bit, hopefully it's less confusing now#2021-04-2211:18tobiasOK, got it! So LSP + clj-kondo has all the same functionality as filewatcher + clj-kondo. Thank you! BTW, I'm a huge fan of the tools you've created. I use Babashka for scripts now and it's awesome.#2021-04-2212:24ericdalloclojure-lsp should work with intellij indeed: https://clojure-lsp.github.io/clojure-lsp/clients/#intellij-cursive#2021-04-2214:51euccastroI'm making a macro that should be linted like a let with ternary bindings (it's an in-house convenience gizmo and there's a method to my madness...) something like:
(with-new [a "app/object" {:label "a"}
           b "app/type" {:id 25}]
  (str a b))
#2021-04-2214:52euccastrois there a way to tell clj-kondo how to lint this?#2021-04-2214:52borkdude@euccastro either disable the unresolved-symbol linter in this macro or write a hook#2021-04-2214:53euccastrothanks! I'll take a look at hooks... worst case, I'll require the second and third expression to be within a vector and then I guess I can just lint it like a let , right?#2021-04-2214:54euccastroi.e.,
(with-new [a ["app/object" {:label "a"}]
           b ["app/type" {:id 25}]]
  (str a b))
#2021-04-2214:56delaguardothen clj-kondo will not help in case ["app/type"]#2021-04-2214:59borkdude?#2021-04-2215:01euccastroI think he means it won't flag it as an error? I'm fine with that#2021-04-2214:59borkdude@euccastro that syntax should work I think#2021-04-2217:39euccastroIt does work indeed, thank you very much!#2021-04-2308:22imreHey all. Does the clj-kondo cli have some sort of quiet switch? I'd like to disable its output when linting deps in CI. Piping it into devnull works fine locally but Jenkins seems to ignore that#2021-04-2308:35borkdude@imre what about piping to /tmp/output.txt ?#2021-04-2308:36borkdudeThere is an issue here where we discuss such a flag: https://github.com/clj-kondo/clj-kondo/issues/1262 Feel free to read and comment.#2021-04-2308:56borkdude@imre Oh btw, there is already a command line arg for linting deps: --dependencies#2021-04-2312:20imrethank you, will have a look at it#2021-04-2818:17imretried that flag and it's almost precisely what I was looking for, thank you#2021-04-2818:18imreHowever, on subsequent runs it will stderr stuff like mount-0.1.16.jar was already linted, skipping - any way to disable that too?#2021-04-2818:20borkdude
>/dev/null 2>&1
perhaps?
#2021-04-2818:52imreYeah, that's what our CI will ignore for some reason. No worries, this is already halfway there, thank you#2021-05-0318:51imreThat ended up working actually in the end, thank you!#2021-05-0318:51borkdude:thumbsup:#2021-04-2308:56borkdudeThen no findings will be reported at all#2021-04-2310:34rickmoynihan@borkdude: regarding our discussion here: https://github.com/clj-kondo/clj-kondo/issues/1262#issuecomment-824884105 I just tried: clj-kondo --lint ./src --config '{:output {:level :error}}' and it still displays warnings, am I doing something wrong?#2021-04-2310:37borkdude@rickmoynihan We don't yet support that, but it was a proposal, since CLI args should be supported in the programmatic interface as well usually#2021-04-2310:37rickmoynihanah gotcha#2021-04-2310:37borkdudeand we already have an :output config entry#2021-04-2310:37rickmoynihanI meant to actually ask about that regarding the --fail-level stuff#2021-04-2310:38borkdudethe programmatic interface never "fails" so that is pretty CLI specific#2021-04-2310:40rickmoynihanyeah it definitely doesn’t make sense for --fail-level itself… anyway good to know that’s generally the intention.#2021-04-2312:53borkdudeNew clj-kondo release: 2021.04.23 with several bugfixes / improvements. https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#20210423#2021-04-2315:37StefanHi! I just noticed https://github.com/clj-kondo/clj-kondo/issues/682 and deduced that orchestra defn-spec should now be recognized when configuring it (`orchestra.core/defn-spec clj-kondo.lint-as/def-catch-call}`). It doesn’t seem to work for me though. When I have this in my source code:
(defn-spec xx ::myspec [foo nat-int?] foo)
I get these errors:
src/foo.cljc:103:12: error: Unresolved symbol: xx
src/foo.cljc:103:25: error: Unresolved symbol: foo
Am I doing something wrong? (This is with latest version of clj-kondo btw)
#2021-04-2316:41borkdude@stefan.van.den.oord It should be orchestra.core/defn-spec clj-kondo.lint-as/def-catch-all, catch-all, not catch-call#2021-04-2316:42borkdudeYou are the second person who mentions catch-call, is this a typo somewhere?#2021-04-2317:24StefanYeah I copy-pasted that from here: https://github.com/clj-kondo/clj-kondo/commit/fd7dc08d61ce014c171452298cd47139e506d8cd#diff-128a3f9ffa6a6f3863e843089ede6d07010215acf49c66b2d1f1d9baba2f49e7R85#2021-04-2317:25borkdudeThat has been corrected since ages#2021-04-2317:26StefanYeah. I got there via the #682 issue. Didn’t spot the error and just copy-pasted it.#2021-04-2317:26StefanBut thanks for helping out, it works now! 🎉#2021-04-2413:21Duck NebuchadnezzarIs there a good way to get a repl with all of the namespaces in my :requires key processed? (also the default commands)#2021-04-2413:39borkdude@duck Is this for #babashka? :)#2021-04-2414:23Duck Nebuchadnezzaroops, it was#2021-04-2416:13mike_ananevWhy, If I have .clj-kondo/config.edn all warnings and errors disappears in IDE (Emacs, Cursive)? If I delete .clj-kondo/config.edn then all warnings returns in IDE. contents of .clj-kondo/config.edn
{:output        {:exclude-files [""]}

 :linters       {:consistent-alias
                 {:aliases {clojure.string   string}}

                 :unresolved-namespace
                 {:exclude [user criterium.core]}

                 :unresolved-symbol
                 {:exclude [(cljs.test/are [thrown? thrown-with-msg?])
                            (cljs.test/is [thrown? thrown-with-msg?])
                            (clojure.test/are [thrown? thrown-with-msg?])
                            (clojure.test/is [thrown? thrown-with-msg?])]}

                 :unsorted-required-namespaces
                 {:level :warning}

                 :unused-referred-var
                 {:exclude {clojure.test [is deftest testing use-fixtures]}}}

 :skip-comments true}
#2021-04-2416:14borkdudeI suspect this is the culprit: :output {:exclude-files [""]}#2021-04-2416:14borkdudethe empty filename always matches any file probably#2021-04-2416:16borkdudeit's a regex#2021-04-2416:18mike_ananevthanks! if I put {:exclude-files ["target"]} all warnings became visible!#2021-04-2419:53dgrI’ve got a clojure.test file that is using (:require [foo.core :refer :all]) in the namespace declaration. All the symbols that should be referred by that are being flagged later on as error: Unresolved symbol: bar. Is that expected or a bug? If I use :refer [bar], it is not flagged. This is with the latest version of clj-kondo installed on latest MacOS Big Sur via Homebrew.#2021-04-2419:53borkdude@droberts3 Did you not have that with the previous version of clj-kondo?#2021-04-2419:55dgrI don’t know. I haven’t gone back and installed a previous version to figure it out. I wanted to ask here before I tried to debug it too much further. I was thinking that maybe clj-kondo didn’t pull in required namespaces on purpose (performance?) and was just using the static symbols in a :refer form in the file itself.#2021-04-2419:56dgrIt’s pretty common in unit tests to use :refer :all to pull in everything in the namespace under test.#2021-04-2419:56borkdude@droberts3 It's a bit of a gray area. Since clj-kondo is a static analyzer and pretty much just lints what you throw at it, without inspecting other stuff on your filesystem, this can be hard. But chances are that when you also have linted foo.core while also having a .clj-kondo dir so it can save information there, that this will work correctly#2021-04-2419:58borkdudeI think that should work even. So can you maybe do:
mkdir -p .clj-kondo
clj-kondo --lint src:test --dependencies
and then check again in your editor after making an edit?
#2021-04-2419:59borkdude(the --dependencies flag is telling clj-kondo to not emit any output because you are linting only for populating the cache)#2021-04-2420:00dgrAh. Let me try this. I don’t have a .clj-kondo directory as I have just been using straight defaults.#2021-04-2420:00dgrYep, that worked#2021-04-2420:00dgrThanks!#2021-04-2513:32yuhanDoes clj-kondo know about filenames and could it warn if a namespace name doesn't match up with its directory structure and filename?#2021-04-2513:39borkdude@qythium There is an issue for this where there is a discussion. Feel free to chime in there#2021-04-2513:49yuhanoops, should have checked first! I was just wondering because clj-kondo doesn't seem to have any static knowledge of the classpaths, so it couldn't tell how far up the directory tree to go to infer a file's "correct" ns name#2021-04-2515:00borkdude@qythium that's correct, although we can apply some heuristics maybe#2021-04-2704:10jayDoes clj-kondo support auto-fixing all the warnings? I wasn’t able to find anything around that in the docs, so just wanted to make sure#2021-04-2707:53borkdude@jay954 No. For automatically fixing stuff, I can recommend you take a look at #lsp#2021-04-2716:56jaythank you! will check it out :thumbsup:#2021-04-2713:29papachanTo allow a foo macro with clj-kondo lint do i have to macroexpand the macro at the beginning of the namespace every time? if there have many macro to register under clj-kondo what would be the steps to follow?#2021-04-2715:20papachanOh just found how state-flow manage their macros with clj-kondo exports https://github.com/nubank/state-flow/blob/master/resources/clj-kondo.exports/nubank/state-flow/config.edn#2021-04-2812:32dvingohi @borkdude I am not seeing any warnings when linting deps.edn:
$ head deps.edn
{:paths   ["src/main" "resources"]

 :jvm-opts [""]
 :deps    {org.clojure/clojure                      {:mvn/version "1.10.3"}
           org.clojure/spec.alpha                   {:mvn/version "0.2.194"}
           bk/ring-gzip                             {:mvn/version "0.3.0"}
           com.taoensso/timbre                      {:mvn/version "5.1.2"}
           com.taoensso/tufte                       {:mvn/version "2.2.0"}
           ;; this version breaks tracing...
           ;com.wsscode/pathom                       {:mvn/version "2.3.0"}
$ clj-kondo --lint deps.edn
linting took 11ms, errors: 0, warnings: 0
I'm not sure if I'm invoking it incorrectly..
#2021-04-2812:34borkdude@danvingo Try this example:
{:deps {medley {:mvn/version "RELEASE"}}}
#2021-04-2812:34borkdudeIt doesn't yet have a check for the toplevel jvm-opts, but like I said, you're welcome to create an issue for it#2021-04-2812:35dvingoahh, sorry, now I understand what you meant#2021-04-2914:42Yehonathan SharvitA linter idea: When a defmulti is defined as a keyword, warns in case the arity of one of the methods is greater than 1. Otherwise keyword-as-a-function treats the second argument as a default value. This mistake in my code caused an out of memory error due to the caching mechasim of multi-methods. https://ask.clojure.org/index.php/10532/memory-leak-using-the-default-method-of-a-multimethod#2021-04-2914:48borkdudeThanks. It's a pretty niche problem I think, but I'll keep it in mind#2021-04-2916:20Yehonathan Sharvitvery niche but when it happened it cost me 5 days of painful of investigation with all kind of JVM profiling tools#2021-04-2914:58Darin Douglassspeaking of: thoughts on having a linter that checks that a defmulti dispatch fn is a var? if you provide a fn, trying to later change that fn in a repl is tricky#2021-04-2915:02borkdudealso sounds pretty niche :)#2021-04-2915:03borkdudedo you mean: give a warning so you can remove it before going into production?#2021-04-2915:25Darin Douglassi guess you could consider it niche, though i suspect it's good practice everywhere defmultis are used#2021-04-2915:26Darin Douglassit'd definitely be a warning, though in production theoretically fn dispatch values are ok since you shouldn't be mucking around in a repl in production 😛#2021-04-2915:27borkdudeI don't understand which of the two you find good practice#2021-04-2915:29Darin Douglass
;; this is better than ...
(defn dispatch
  [args]
  <some logic>)

(defmulti my-multi #'dispatch)

;; ... this
(defmulti my-multi (fn [args] <some logic>))
#2021-04-2915:30borkdudeand you want clj-kondo to warn on the latter? I don't think I agree with this, but maybe I just haven't run into trouble enough with re-defining multi-methods. In my experience this is pretty rare.#2021-04-2915:33Darin Douglassi think it would be useful, we've been hit a couple of times by it. the solution is to just reload your repl, but still it's annoying#2021-04-2915:41didibusYou don't need to reload the REPL#2021-04-2915:42didibusJust do: (def my-multi nil) and then re-evaluate the defmulti and it's going to work#2021-04-2915:42Darin Douglassoh interesting, i hadn't thought of that#2021-04-2915:43Darin Douglassi'll have to rethink my stance then (though i suspect i'll still lean towards the "use a var" side)#2021-04-2915:44didibusTo be honest, I don't know why defmulti behaves as it does, but for some reason they went above and beyond to prevent it from being redefined and I wonder why, like is there a good reason#2021-04-2915:45didibusWhat I tend to do is this:
(def my-multi nil)
(defmulti my-multi (fn [...] ...))
That way when I reload the namespace in the REPL it reloads the defmulti as well in case I changed the dispatch-fn. But in prod I'm not messing with the standard defmulti in case there's a reason it is how it is.
#2021-05-0110:30jeroenvandijk@U0K064KQV The reason you don’t want to redefine multimethods is because this would remove all extensions in other namespaces potentially. For this same reason (def my-multi nil) is not (always) a good idea. I’m using the trick of @UGRJKK74Y as well. I don’t use defmulti in performance heavy areas normally so (defmulti my-multi #'dispatch) is a better approach for my workflow#2021-05-0110:39didibusI saw that, normally actually I have it in a comment block above and I just know to evaluate it in my REPL after I changed my dispatch FN#2021-05-0110:40didibusMost of the time, when I change my dispatch-fn, it's because it didn't work and I don't mind re-evaluating the defmethods afterwards#2021-05-0110:41didibusBut I see the advantage of Var indirection over it, appart for performance, seems you get all the benefits and none of the negatives#2021-05-0110:42jeroenvandijkyeah for me it was the best approach. I have a project where I have 5 or more namespaces extending one multimethod. So this means i have to reload those 5 namespaces. I have had long debugging sessions because of this. So I decided to always go for the var approach#2021-05-0110:45jeroenvandijkMaybe the idea of having a macro that would remove the indirection in production could be useful here. To remove the performance argument#2021-04-2915:34borkdudeOriginally I thought you were arguing the opposite: don't use a var because this is worse for performance :)#2021-04-2915:34borkdudeI guess you could even write (when dev? #'foo foo).#2021-04-2915:35Darin DouglassAh yah, rereading what I typed I can see the confusion, sorry bout that :P#2021-05-0317:38Ory BandHi. I have some things in midje i'd like clj-kondo to stop notifying me about: • midje's tabular tests: specifically the table column headers such as ?this and ?that (the string after the question mark is generic). any idea how can i do that? https://github.com/marick/Midje/wiki/Tabular-facts • referring and calling private fns using testable-privateshttps://github.com/marick/Midje/wiki/Private-functions AND https://github.com/marick/Midje/wiki/Using-private-functions-in-prerequisites any idea what i should put in clj-kondo config.edn to solve these? thank you#2021-05-0318:22borkdude@ory.band Have you already read: - https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md - https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md Have you already tried something?#2021-05-0318:24Ory BandYes. The thing is, these scenario are kinda unique: • i haven't found a way to solve the tabular issue. it's an unresolved symbol. i would like unresolved symbol errors, just ignore ones starting with ?xxx and only for unit test files • for private calls, i'd like to silence the warning but only for unit test files whose filenames are t_my_test_file.clj (has a t_ prefix)#2021-05-0318:28borkdudeyou can use namespace local config to disable a linter in a namespace, or you can use local config like #_{:clj-kondo/ignore [:private-call]} to ignore things locally#2021-05-0318:29borkdudethe other option is to write a custom hook to make clj-kondo understand midje#2021-05-0318:30borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md once you have a hook that works, you can submit it to https://github.com/clj-kondo/config so other can profit from it too#2021-05-0318:30borkdudeto suppress private call warnings you could also use #'foo/bar instead of foo/bar#2021-05-0318:33Ory Bandthanks! good ideas. is there no way to configure clj-kondo for specific namespaces starting with t- or filenames starting with t_ ?#2021-05-0318:33borkdudenot currently#2021-05-0318:34Ory Bandok. thank you#2021-05-0318:34borkdudeyou can disable it completely based on the filename though#2021-05-0318:35Ory Bandyeah but you have to provide exact "fully qualified" full file names right?#2021-05-0318:35borkdudeno, it works on a regex#2021-05-0318:35Ory Bandisnt that what i'm looking for?#2021-05-0318:36borkdudeI don't think so since you said you still want linting except for some things#2021-05-0318:36Ory Bandah you meant disable clj-kondo completley? i thought just specific linters#2021-05-0318:37borkdudethat isn't currently possible, it's only possible in the namespace metadata for one specific namespace at a time#2021-05-0318:37Ory Bandthat would do for the private call notification. but for tabular i agree i'll prolly have to write some custom linter/hook#2021-05-0318:37Ory Bandok, thanks#2021-05-0318:37Ory Bandgot ya#2021-05-0320:00Fredrik WallbergIs there a way to register custom specs which can be referenced in the :type-mismatch linter? Example:
{:level :error
 :namespaces {foo {bar {:arities {1 {:args [:custom-spec-label-here]}}}}}}
#2021-05-0320:03Fredrik WallbergContext: when writing annotations for multiple functions operating on the same (complex) map, it would be great to reference the map/spec by name.#2021-05-0320:11borkdude@wallberg no, these keywords currently only refer to a set of predefined types#2021-05-0320:13Fredrik WallbergThat explains why I didn't find it in the documentation. Thanks for the swift reply and a great tool!#2021-05-0409:07pinkfrog@borkdude Is it possible to tell carve to ignore a clj file, instead of some symboles#2021-05-0409:08borkdude@i carve has :api-namespaces where it won't look at public unused vars, maybe this works for you?#2021-05-0409:09borkdudeit uses the name of the namespace, not the filename#2021-05-0409:15pinkfrogIs this the correct form?#2021-05-0409:15pinkfrog
{:api-namespaces ['mocks]}
#2021-05-0409:15pinkfrog
❯❯❯ clojure -M:carve --opts '{:paths ["src"]}'                                                                                     

Carving src/mocks.cljs

Found unused var:
------------------
(def action-button          #js {:default #js {:Item #js {}}})
------------------
Type Y to remove or i to add mocks/action-button to .carve/ignore
#2021-05-0409:15pinkfrogStill got the above output.#2021-05-0411:00pinkfrogLooking at the test sample: https://github.com/borkdude/carve/blob/f499f65e36e02484609f01ce891f3c0207b24444/test/carve/main_test.clj#L66#2021-05-0411:00pinkfrogthe {:api-namespaces [’mocks]} should be correct. But it doesn’t work on my side.#2021-05-0411:00borkdudewhere did you put this?#2021-05-0411:01borkdudein an EDN file you should not use the quote#2021-05-0413:40pinkfrogThanks. Removing the quote makes it work.#2021-05-0413:40pinkfrogIs it possible to instruct carve to ignore all clj files that has the name of xxx_test.clj ?#2021-05-0413:41borkdude@i carve should already ignore deftest vars#2021-05-0413:44pinkfrogThanks. That’s the case.#2021-05-0410:54pinkfrogclj-kondo doesn’t catch unused variables? How to configure it?#2021-05-0410:54borkdudevariables = vars?#2021-05-0410:55borkdudeclj-kondo itself doesn't have that feature, but it's available as part of its analysis output#2021-05-0410:59pinkfrogYup. I was trying to use carve. And suddenly got aware that clj-kondo has the unused feature covered: https://github.com/clj-kondo/clj-kondo#features#2021-05-0410:59pinkfrogSo what DIRECT feature is supported by clj-kondo?#2021-05-0411:00borkdudeclj-kondo only reports unused private vars, not unused public vars#2021-05-0411:00borkdudebut clojure-lsp does#2021-05-0410:55borkdudeyou can use clojure-lsp lens-mode if you want to display usages inline in your editor, which uses this analysis#2021-05-0500:04piyerIf I am planning on using clj-kondo with flycheck do I still need LSP setup?#2021-05-0500:14ericdalloIf you just want lint on your code, you don't need LSP. But if you want lint + refactoring + quick fixes + other IDE features, you'd probably wants to install only lsp-mode and clojure-lsp which already have clj-jondo built-in and give all of that#2021-05-0500:14ericdalloHere you can see all features: https://clojure-lsp.github.io/clojure-lsp/features/#2021-05-0500:27piyer@UKFSJSM38 Thank you!#2021-05-0502:11matheusashtonHello, I'm having an issue with clj-kondo and honeysql because honeysql helpers are macros and clj-kondo doesn't recognize those macros. I tried configuring clj-kondo as in honeysql's https://github.com/seancorfield/honeysql/blob/develop/.clj-kondo/config.edn but now, instead of a unknown symbol warning, I'm getting an error because it expects (select :field1 :field2 :field3) to have only 2 arguments.. anyone had issues like this before?#2021-05-0502:18matheusashtonsolve it adding a config to lint the helper as clj-kondo.lint-as/def-catch-all#2021-05-0509:55Aronhelo, I am trying to use clj-kondo and it tells me Unexpected error. Please report an issue. when I try to lint a file manually#2021-05-0509:56borkdudecan you give more information? please be as detailed as you can.#2021-05-0509:56AronI am not sure if I can.#2021-05-0509:57Aronhttps://imgur.com/a/ZEmqHnG#2021-05-0509:57Aronnot sure if this helps at all#2021-05-0509:58borkdudewell, for example, you could make a screenshot of how you invoke clj-kondo, provide the clj-kondo version, operating system, etc.#2021-05-0509:58AronI can try to localize the issue after work in non-work file#2021-05-0509:58borkdudethis sounds like a configuration error possibly.#2021-05-0509:58borkdudecan you rename the config.edn file to config.bak.edn or something?#2021-05-0509:59Arondefinitely, I will re check the configuration, will take a while. thanks#2021-05-0510:02Aronrenaming does make the error go away, thanks again.#2021-05-0510:03borkdudethis probably means that there is misconfiguration in this file. please let me know what caused it so clj-kondo can provide a better error message#2021-05-0510:12Aron:unresolved symbol :exclude vector had lists without further vectors, just the namespaces#2021-05-0510:12Aronalthough, by mistake I left a () in it, that caused a nullpointer exception 🙂#2021-05-0510:13Aronthanks for the help, now I am trying to write a working config...#2021-05-0510:15Aron:unresolved-symbol {:exclude [(helix.core/defnc) (helix.core/defhook) (kitchen-async.promise)]}}}#2021-05-0510:16Aronand :exclude [ () .... btw. I wouldn't expect anything to work with incorrect config, so I am sharing it mostly to clear it up, not because I think you should do anything about it#2021-05-0510:17borkdudeI think clj-kondo can provide a linter for its own config. We are already linting deps.edn as well#2021-05-0510:20Aronturtles all the way down? 🙂#2021-05-0716:52ericdalloQuestion: Shouldn't https://github.com/clj-kondo/clj-kondo/issues/598#issuecomment-551948021 be a default on clj-kondo?#2021-05-0716:53ericdalloSince it's from clojure.test#2021-05-0717:39borkdudeIt's not clojure.test but it is one of the "core" libraries, so yes, I think we should have built-in support for it#2021-05-0717:40ericdalloyeah, it'd be nice#2022-02-2123:34ericdalloJust faced this again facepalm I should have opened a issue 😂#2022-03-0320:45borkdudefixed#2022-03-0320:47ericdallo🙏 thanks#2021-05-0720:24ericdalloIs it possible to add a hook to understand https://github.com/marick/Midje/wiki/Tabular-facts custom vars? 🧵#2021-05-0720:25ericdallofor example:
(tabular
  (fact "foo"
    (+ ?a ?b) => ?res)
  ?a ?b ?res
  1  2  3)
#2021-05-0720:25borkdudeanything is possible with hooks#2021-05-0720:26borkdudeit seems like an are macro gone wild (in my opinion the are macro is already quite wild)#2021-05-0720:27ericdalloyes, I don't like it either 😅 but is used in a lot of legacy projects#2021-05-0720:27ericdalloBut I imagine a lot of people use midje and would like to have that working nice#2021-05-0720:27ericdalloso, I imagine a hook built-in in the lib would be the best, right? (like we did for state-flow)#2021-05-0720:29borkdudewhat's state-flow again?#2021-05-0720:32ericdallothe "new" midje hahah https://github.com/nubank/state-flow#2021-05-0720:32ericdallothat uses clojure.test as base#2021-05-0720:29borkdudeyeah, either in the midje or clj-kondo/config lib#2021-05-0720:33ericdalloso, how the hook would mark the ?foo vars as locals , is there any hook that makes that as an example?#2021-05-0721:09borkdude@ericdallo The built-in core.match support would be something to look at#2021-05-0721:10borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/analyzer/match.clj#2021-05-0721:12borkdudeit is different because it calls other clj-kondo internals directly, so it doesn't first macro-expand into something else, but it might give some ideas#2021-05-0721:16borkdudethe best way to think about hooks is probably: write a macro-expansion that translates your code into built-in clojure forms, but it doesn't actually have to work, as long as the generated code can be linted. And then rewrite the macro-expansion into code that actually moves around/generates nodes instead of s-expressions.#2021-05-0721:35ericdalloIt makes sense! thank you!#2021-05-0817:36ericdalloit worked, I created https://github.com/marick/Midje/pull/474 🙂#2021-05-0818:13borkdude@ericdallo but test-resources don't end up in the artifact?#2021-05-0818:16ericdalloit seems it ends up :man-shrugging: https://github.com/marick/Midje/blob/master/project.clj#L31#2021-05-0818:16ericdalloAlso, I tested it with local release and it worked#2021-05-0818:17borkdudeoh that's weird :)#2021-05-0818:17ericdalloYeah, agreed#2021-05-1115:17ericdalloDoes clj-kondo merge home config with a project specific one? 🧵#2021-05-1115:18borkdudeyes#2021-05-1115:18ericdalloI noticed if I have a home config with a custom :lint-as and add a project config that has also a :lint-as but both lint-as are different, clj-kondo doesn't merge it#2021-05-1115:18ericdalloit uses the project one only#2021-05-1115:18ericdallois that right?#2021-05-1115:19borkdudeI think it should merge it#2021-05-1115:19borkdudethe project is merged in later, so the project config wins from the global config#2021-05-1115:19ericdalloexample: home
:lint-as {a b}
project
:lint-as {c d}
I would expect a final config of
:lint-as {a b
          c d}
#2021-05-1115:19borkdudeyes, that should be the case#2021-05-1115:20borkdudeyou can verify this if you call run! and then inspect the :config key in the result#2021-05-1115:20ericdallohum, I will try to make a minimal repro, but it seems to me the final result is:
:lint-as {c d}
#2021-05-1115:20borkduderepro welcome#2021-05-1115:20ericdallois there any easy way to test it via cli?#2021-05-1115:21borkdudeno#2021-05-1115:21ericdalloalright#2021-05-1115:43ericdalloLMK if I'm doing anything wrong: https://github.com/clj-kondo/clj-kondo/issues/1279#2021-05-1115:44borkdudeoh btw, there is also a clj-kondo.core/merge-configs function, you could test this#2021-05-1115:46borkdude
user=> (clj-kondo/merge-configs '{:lint-as {a b}} '{:lint-as {c d}})
{:lint-as {a b, c d}}
#2021-05-1115:46ericdalloOh, nice, so why is not working for my case?#2021-05-1115:47borkdudeIf you remove the project config, does it still use the home one - is your home config used at all?#2021-05-1115:48borkdudeyou should put your config in ~/.config/clj-kondo or XDG_CONFIG_HOME/clj-kondo#2021-05-1115:56ericdalloyeah, for some reason, clj-kondo is not detecting the home config, only if I move it to xdg-config one#2021-05-1115:57ericdallolet me confirm if now it gets merged correctly#2021-05-1115:57borkdudethe config should be in ~/.config/clj-kondo, not in ~/.clj-kondo#2021-05-1115:57borkdudebut XDG_CONFIG_HOME overrides this#2021-05-1115:58borkdudelike it should#2021-05-1115:58ericdallofor some reason the home one always worked :thinking_face:#2021-05-1115:58ericdallodoes that support was dropped recently?#2021-05-1115:59borkdudeno, it has always worked like this#2021-05-1116:00borkdudeit was implemented in issue 992, you can still find the commits#2021-05-1116:00borkdudehttps://github.com/clj-kondo/clj-kondo/commit/c76485e34daf0aeb4b1d5f41f7af9ee3c540ef4e#diff-256c8638a8470c10da0585978efbf091f39fbe7441c7361489dd6b90b29fbe67#2021-05-1116:01ericdallothe merge works fine now 🙂 That's crazy, in nubank we always used the config on ~/.clj-kondo/config.edn and it always worked
#2021-05-1116:01ericdalloanyway, I'll update the config location#2021-05-1116:01ericdallothanks for the help 🙂#2021-05-1116:03borkdudehttps://github.com/clj-kondo/clj-kondo/blob/cc4e552ef5207e7928d2093bdb9acf09e0dcc9d1/src/clj_kondo/impl/core.clj#L99#2021-05-1116:04borkdudeThis is the first commit where the home config was read: https://github.com/clj-kondo/clj-kondo/commit/edd4ff14c286c644921cd84f874ff007699f01f4#diff-abd35172092e4f3c0969a9f59bd79ed193be63b1107549915d49758fae78bee7#2021-05-1116:04borkdude
(defn home-config []
  (let [home-dir  (if-let [xdg-config-home (System/getenv "XDG_CONFIG_HOME")]
                    (io/file xdg-config-home "clj-kondo")
                    (io/file (System/getProperty "user.home") ".config" "clj-kondo"))]
    (when (.exists home-dir)
      (read-config-from-dir home-dir))))
#2021-05-1116:04borkdudethat function is still the same today#2021-05-1116:07ericdalloyeah, it makes sense, I still don't understand how that was/is working for a lot of people#2021-05-1116:07ericdallomaybe clj-kondo is checking recursively until / for a config?#2021-05-1116:07borkdudeyes#2021-05-1116:07borkdudeit does#2021-05-1116:07ericdallooh, so that makes sense now#2021-05-1116:08ericdalloit was indeed using the home one when there is no project one#2021-05-1116:08ericdalloeverything makes sense now hahah#2021-05-1116:08ericdallobecause it was not considering as a home config bug a project config#2021-05-1116:08ericdallothe home config must be on XDG or .config#2021-05-1116:53ericdallo@U04V15CAJ I think I found a bug with a copy-configs, sorry for bother you again 😅 • I have a .config/clj-kondo config with :config-paths ["nubank/state-flow"] • if the project doesn't contains a .clj-kondo dir, everything works, since clj-kondo copy the lib config to the global clj-kondo location and the config-paths works. • if the project has a .clj-kondo dir, clj-kondo will copy the lib config to the project clj-kondo, but the :config-paths from the global one will not work and the project will not have the lib config configured correctly#2021-05-1116:53ericdallodoes that makes sense for you?#2021-05-1116:53ericdallomaybe copying the config for both places (global and project) would work?#2021-05-1116:58ericdalloI confirmed that adding :config-paths ["nubank/state-flow"] to the project clj-kondo config works, so I think that's the issue, clj-kondo should check for config-paths on both configs and if finds, it should check for the folders on both config dirs as well#2021-05-1117:13borkdudeI was afk for dinner, let's see#2021-05-1117:14borkdudeyes, this makes sense. you should add :config-paths to the clj-kondo directory that is relative to the copied configs#2021-05-1117:15borkdudeI think you should just re-import your configs once again, if you decide that your project is going to have a .clj-kondo config#2021-05-1117:15borkdudeI don't expect this occurs very often in the lifecycle of a project (just one time)#2021-05-1117:44ericdalloYes, my point is that clj-kondo is copying the config to the project one but the config with the config-paths is on the global one#2021-05-1117:44ericdalloSo it doesn't find the confif#2021-05-1117:45borkdudeyes, this is because you introduced the local config later#2021-05-1117:45ericdalloI think this is the same issue @U95713QV7 was having#2021-05-1117:45borkdudewhich should not happen that frequently in the lifecycle of a project#2021-05-1117:47borkdudewhere is this issue filed in the issue tracker? I have not heard about it before#2021-05-1117:48borkdudebut in my opinion this is just how it works, I don't think clj-kondo has to look in multiple places. it tells you that you should add a config dir to your local config if you copy the configs#2021-05-1117:48borkdudeif you don't agree with how that works, you can move your config to the global config as well, manually#2021-05-1117:49borkdudeperhaps I am missing something, but I'm kind of tired today and perhaps explaining it crystal clear in an issue helps#2021-05-1117:49borkdudeand I can look it at some other day with fresh eyes#2021-05-1117:49ericdallothe issue was in some other thread 😅 My point is just that we'd like to avoid manual moves or something like that to work well will everyone that use the project, I'll try to simulate a local repro to make sure we are talking about the same thing#2021-05-1213:06ericdalloRelated to this ☝️ I created this issue: https://github.com/clj-kondo/clj-kondo/issues/1281#2021-05-1214:19borkdudeI will get to it, currently afk #2021-05-1313:40ericdalloAbout https://github.com/clj-kondo/clj-kondo/issues/1281 🧵#2021-05-1313:40ericdallo@U04V15CAJ should we create a new flag since if we change the --copy-configs to accept a file, the old empty --copy-configs will stop working, right?#2021-05-1313:41borkdudewithout anything or nil we just use the previous stategy, I'd say: the local .clj-kondo dir#2021-05-1313:42ericdalloGot it, I'll follow with that so#2021-05-1314:02ericdallo@U04V15CAJ it seems there is a place that still treat the ~/.clj-kondo as a global config dir: https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/core.clj#L102#2021-05-1314:03ericdalloIf we change here to check the XDG/.config dir as well, it would behave the same and fix the issue, right?#2021-05-1314:04ericdalloso the ~/.clj-kondo has indeed a special handling, I thought clj-kondo was using it because of a recursive call from the project dir#2021-05-1314:04borkdudeoh damn, I don't know where that comes from#2021-05-1314:06ericdalloI found that checking why it needs to cfg-dir be non-nil: https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/core.clj#L241#2021-05-1314:58borkdudeOh btw, that line is correct#2021-05-1314:58borkdudeIt just means it searches from the current directory upwards#2021-05-1314:58borkdudeI misread it for user.home#2021-05-1315:00borkdudeif we add the home-config dir as a fallback there, I'm not sure what consequences that has...#2021-05-1315:01borkdudethat's why I would prefer to have an explicit copy-configs destination instead (and use the local dir as the default one)#2021-05-1315:01borkdudeelse it would populate .config/clj-kondo/.cache with data which is probably against the rules of XDG_CONFIG, etc#2021-05-1315:06ericdalloAlright, but that is exactly what I intend to have after I pass the --copy-configs .config/clj-kondo , the cache properly added to that dir, right?#2021-05-1315:07borkdudeconfigs = stuff exported by libraries, cache = transit files in .cache, those are two totally different things#2021-05-1315:08ericdalloI see, so I think there are 2 issues here haha#2021-05-1315:08ericdallobecause without a clj-kondo .cache folder, things like refered midje macros and things like that doesn't work#2021-05-1315:08ericdallobecause there is no .cache and clj-kondo doesn't persists it on .config/clj-kondo only if threre is a ~/.clj-kondo#2021-05-1315:09borkdudeyou can control the cache dir with --cache-dir#2021-05-1315:10ericdallohum, so I can --copy-configs ~/.config/clj-kondo --cache-dir ~/.config/clj-kondo on clojure-lsp?#2021-05-1315:10borkdudeyou could, but I would not do this by default for all users of course#2021-05-1315:11ericdallowhy? otherwise only if users manually create local .clj-kondo dir or on home things will work like refered symbols#2021-05-1315:12borkdudeyes, they should create that then. or lsp should create it, I have suggested this before#2021-05-1315:12borkdudeuser should just read the manual how clj-kondo works, it's all documented pretty well#2021-05-1315:12ericdalloit is, my point is just that is not IDEish, imagine cursive ask for users create a .cursive dir for things work 😕#2021-05-1315:13ericdalloI just wanna make most things work by default and leave the corner cases optional for users configure it#2021-05-1315:13borkdudeyeah, so because clojure-lsp is an IDEish thing, it could make that decision I guess. clj-kondo doesn't know where the root of your project is because all it sees is a filename#2021-05-1315:14ericdalloyeah, that's I agree 🙂#2021-05-1315:14ericdalloalright, I already implemented on clj-kondo that support as we discussed, I'll make some tests with clojure-lsp to make sure it makes sense#2021-05-1315:14ericdallothanks for the help 😄#2021-05-1315:15borkdude:)#2021-05-1315:20borkdudemaybe clj-kondo could borrow some of the IDE-ish stuff from lsp in the future, e.g. how to decide where the root of a project is, but so far clojure-lsp is doing a great job of lifting this burden from clj-kondo itself ;)#2021-05-1315:25ericdallohahah yeah, that could make things easier for clojure-lsp and maybe open doors for other libs that use clj-kondo#2021-05-1315:26borkdudethe reason I've refrained from this so far is that I don't like tools that automatically create garbage on my machine#2021-05-1315:30ericdalloyeah, it's sounds good to avoid those things, but as we need a .cache somewhere for things work, we need to choose create a .clj-kondo for the project or a global one (which seems less intrusive as it's one time for all projects?)#2021-05-1315:32borkdudeI'm not a big fan of a global caching dir that multiple projects together use, as this can give clashes with namespaces from different projects#2021-05-1315:33borkdudeadding to the confusion. I think people should just invest 5 minutes to see how it works. this saves everybody time and headaches#2021-05-1315:36ericdalloclojure-lsp could create a .clj-kondo in the project root, but it would not be enough since the :config-paths config are on ~/.config/clj-kondo and it expects that lib configs would be copied to there, not to the local clj-kondo dir#2021-05-1315:37borkdudeI don't think it makes sense to copy the "configs" to ~/.config/clj-kondo either, since they are specific to the project's dependencies. Just check them into the project's git repo#2021-05-1315:38borkdudeNote that one giant blob of global configs will make clj-kondo slower as well, as it has to parse all these configs every time it's started#2021-05-1315:39ericdallothe issue is that we would need to add :config-paths for every project manually, but yeah seems more specific#2021-05-1315:40borkdudeI think that is the better thing to do#2021-05-1315:40ericdallowhat happens with lib hook updates? they would be replaced on local clj-kondo as well?#2021-05-1315:41borkdudeyes#2021-05-1315:41ericdalloalright, I'll give a try to check how it works!#2021-05-1315:41borkdudeso different projects can use different versions#2021-05-1315:41borkdudewith a global config that wouldn't work anymore#2021-05-1316:01ericdalloso, I seems to work if the project has a .clj-kondo with the config-paths, and it sounds the cacnonical way to do that, I'll let you know if works for eveybody, thanks!#2021-05-1316:02borkdude:thumbsup:#2021-05-1615:39Felipe MarquesHi, all! I'm trying to integrate clj-kondo in spacemacs, but I'm having some problems. I followed the instructions here: https://cljdoc.org/d/clj-kondo/clj-kondo/2021.04.23/doc/editor-integration#spacemacs But flycheck is not enable by default, I must run SPC t s to toggle the syntax-checking, even after doing (setq global-flycheck-mode t) in my .spacemacs file. Does anyone had the same problem? Thanks in advance 😄#2021-05-1615:40borkdude@marques.goncalves.fel you can try to cross-post to #spacemacs as well#2021-05-1615:42Felipe MarquesThanks! Didn't know there was this channel 😅#2021-05-1805:26Adam HelinsHey! I wrote a macro that does templating like the syntax quote (with ~ and {:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "483608"}, :content ("[email protected]")}). The idea is very similar to https://github.com/brandonbloom/backtick Kondo struggles with it since it lints the given form like any Clojure code. That would be easily solved if there was a "lint as syntax quote" option. Maybe is there already something resembling that?#2021-05-1812:50borkdude@adam678 Probably writing a hook for this is your best bet, or suppress warnings inside this macro#2021-05-1812:50borkdudeI have one similar macro like this called $ which is part of babashka.process. clj-kondo has built-in support for that#2021-05-1812:51borkdudeso perhaps you could look at its code#2021-05-1812:51borkdudehttps://github.com/clj-kondo/clj-kondo/blob/4f1252748b128da6ea23033f14b2bec8662dc5fd/src/clj_kondo/impl/analyzer/babashka.clj#L8#2021-05-1813:03Adam HelinsOkay, thanks! Writing those hooks is always a fun puzzle (well, maybe not always)#2021-05-1813:04borkdude@adam678 In your case, just expanding the body from (your-macro ...) to
`(do ...)
should be sufficient?
#2021-05-1813:04borkdudeWe could have some :lint-as support for this, but it seems pretty rare#2021-05-1813:07Adam HelinsI'm going to do some experiments now, I believe I should rather traverse the given form and extracts everything enclosed in (clojure.core/unquote ...) and (clojure.core/unquote-splicing ...)#2021-05-1813:07Adam HelinsWhat's encapsulated in those will always be valid Clojure, whereas everything outside is actually Convex Lisp in my case#2021-05-1814:24Adam HelinsIs there a way for interacting with QuoteNode ? Any node manipulation must happen via the hook api, right?#2021-05-1814:27borkdudehmm, good point, there is probably no way to generate a syntax-quote, but a normal quoted one can be generated using (list-node (list* (token-node 'quote) ...))#2021-05-1814:39Adam HelinsI think I can manage, with a little indirection. It's more about recognizing literal unquoting (combination between returning false on list-node? and guessing unquote and unquote-splicing from the sexpr).#2021-05-1814:40Adam HelinsIs there an obvious reason why you removed support for map nodes?#2021-05-1814:42borkdudeyeah, the rewrite-clj around map-nodes and namespaced-map-nodes wasn't stable yet#2021-05-1917:21Felipe MarquesHi, everyone, Is there some lib or rewrite-clj script that performs some basic fixes like remove unused namespaces or remove unused binding reported by clj-kondo?#2021-05-1917:22borkdudePerhaps there are also girls here :) I think #lsp can possibly help you with that. Unused namespaces for sure.#2021-05-1917:22Felipe MarquesSorry! 😅 Going to use a more gender neutral term next time!#2021-05-1917:23borkdudeNo worries, I just want to make sure that there can also be girls here :)#2021-05-1917:24Felipe MarquesYou're are totally right!#2021-05-1917:22borkdudeIn the future https://github.com/borkdude/carve may also try to do this, but it doesn't currently#2021-05-1917:23Felipe MarquesCool! Thanks for the info, going to take a lot in it.#2021-05-1917:42lilactownI've just started using clj-kondo and I'm trying to figure out how to configure it in our monorepo#2021-05-1917:45lilactownis there a way for clj-kondo to tell me what config file it is detecting?#2021-05-1917:46borkdude@lilactown clj-kondo walks up to the first .clj-kondo dir it encounters#2021-05-1917:46borkdudepersonally I create a .clj-kondo for each project in a mono-repo#2021-05-1917:47lilactownwhy is that?#2021-05-1917:47lilactownwe have a lot of projects 😬#2021-05-1917:48borkdudesmaller configs have better startup time :)#2021-05-1917:48borkdudealso we have some projects with overlapping namespaces#2021-05-1917:49borkdudeif that isn't a problem, you can choose to have only one .clj-kondo dir, but this also makes linting your classpaths a bit more complicated I think#2021-05-1917:49lilactownyeah that's what i'm thinking through rn#2021-05-1917:49borkdudeyou could script it using babashka or so#2021-05-1917:50borkdudeyou can also put common config into one directory and then refer to it using :config-paths#2021-05-1917:50lilactownfirst step is I want editor integrations to work well, since a lot of our jr devs are using VS Code + Calva and running into lots of squigglies due to our custom macros#2021-05-1917:52lilactownperhaps that's the best; create common configurations for e.g. services, ui, libraries in the top-level and then each project can refer to the appropriate one#2021-05-1917:52lilactownI suppose for step 2, linting in CI, I would want to run clj-kondo in each sub project, or script it with babashka like you were saying?#2021-05-1917:53borkdudeyeah, you can do that, just iterate through the projects.#2021-05-1919:04lilactownI ended up creating a shared config in our app root:
.clj-kondo/ui/config.edn
and added configs to our ui projects that refer to it via :config-paths . it's working well, and gives us room to add service and api configs later. thanks for the guidance! 😄
#2021-05-2013:53grumpletDoes anybody have a config.edn that stops cljs-ajax GET and POST being marked as unresolved vars. I’ve tried variants of this so far to no avail:
linters {:unresolved-symbol 
         {:exclude [GET POST]}}
#2021-05-2013:57borkdude@grumplet I think this should be fixed if you do {:lint-as {ajax.macros/easy-api clojure.core/def}}#2021-05-2013:57borkdudeand then lint the cljs-ajax dependency once again#2021-05-2013:57grumpletThanks 🙂 - I’ll give it a go!#2021-05-2014:09grumplet@borkdude - yep that worked 🙂 - I had convinced myself that :lint-as def wouldn’t work because my source didn’t refer to the easy-api directly - only to GET and POST.#2021-05-2014:11borkdudeHow it works: when it lints the ajax.core namespace clj-kondo collects the vars and stores them in a cache. but with the macro it doesn't know what to do, unless you have some config for it. using the above config, clj-kondo will also treat the macro as def and so it stores the var names in the cache. So when using the ajax.core namespace, clj-kondo now knows about the GET etc var in the ajax.core namespace and they are no longer unresolved.#2021-05-2018:54Joshua SuskaloThanks for a great linter! I just added kondo hooks for the macros in https://github.com/IGJoshua/farolero/tree/feature/clj-kondo-config#2021-05-2018:56borkdudeGreat :)#2021-05-2110:31Jakob DurstbergerI am using calva in VS Code and after looking at the docs I thought the following would suppress the warning. Any idea what I am doing wrong?#2021-05-2110:35borkdude@jakob.durstberger The warning you are seeing here is about an unused var? This is not a linter by clj-kondo, but by clojure-lsp#2021-05-2110:36Jakob DurstbergerYeah “unused public var”. Ah I’ll have a look at clojure-lsp docs then 😄#2021-05-2110:36borkdudeSee https://clojure-lsp.github.io/clojure-lsp/settings/#clojure-lsp#2021-05-2110:39Jakob DurstbergerThank you#2021-05-2517:47mafcocincoNot sure if this is “in the queue” or has been suggested before, but I just ran into an interesting bug that I think clj-kondo could help with. When using a JDBC transaction (i.e. (jdbc/with-db-transaction [tx @db-] …)), I accidentally used the @db- for some of the queries within the scope of the transaction instead of the tx. Seems like clj-kondo could flag this. Not sure if it is specific only to the JDBC transaction macro or if this would be more generally applicable across other macros that introduce scope.#2021-05-2517:51Joshua SuskaloI suspect the intended way to do this would be to add a hook to that macro which adds new findings if it spots that you're using the same form as you did to bind the transaction anywhere in the code.#2021-05-2517:52Joshua SuskaloAnd if this hook is useful, then contribute it back to the original project. Which if this is for next.jdbc might be possible. If it's maintained by cognitect as a part of contrib though, then it might be worthwhile to add such a thing to the hooks that are exposed by clj-kondo.#2021-05-2517:54mafcocincocould you point me to any docs for doing this implementation work? I would be happy to take a stab at it.#2021-05-2517:57Joshua SuskaloThe docs for how to export them are here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration The docs for how to work on the macro hook and emit custom findings is here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md https://github.com/clj-kondo/config/tree/master/resources/clj-kondo.exports/clj-kondo Here's where you'd need to put a new folder if you contribute it back to kondo.#2021-05-2518:01ghadinext.jdbc is not a contrib / cognitect project#2021-05-2517:56borkdude@mafcocinco the jdbc syntax is supported as a built-in feature, so if you use db instead of tx and db would be unused, then that would be reported. I'm not sure what @db- means#2021-05-2518:02mafcocincoYeah, the jdbc syntax works in my version of clj-kondo. I think it is a slightly different bug though. Suppose I have this transaction: (jdbc/with-db-transaction [my-tx my-db] …). So I’m using my-db to create the my-tx binding. In the scope of the transaction, I should be using my-tx for interactions with the DB, running queries, etc. The bug I had was that for one of the queries, I used my-db, which was in scope but caused the transaction to fail because of mutations that were applied to the transaction but not the source db. It occurred to me that if one is using the source DB connection instead of the transaction it has been bound to in the scope of with-db-transaction that that should be flagged as a potential bug.#2021-05-2518:03borkdudeah right, so the right hand side local should not be used anymore in that case. makes sense. what do you think @seancorfield? are there exceptions to this rule?#2021-05-2518:37seancorfieldThere may be exceptions to that, yes, since TX are per-connection. They’re edge cases but it definitely not “always wrong” to use the non-TX version of the connectable.#2021-05-2518:45Joshua SuskaloSo then would that be appropriate to provide as a warning, and then allow users to add ignores in those cases?#2021-05-2518:45Joshua SuskaloOr is the philosophy of kondo to not warn in cases like these where there is a valid usecase?#2021-05-2518:46borkdudeIt can be a configurable opt-in rule#2021-05-2518:46seancorfieldYeah, I think it’s a reasonable warning to add to clj-kondo (for c.j.j and next.jdbc’s equivalent) but occasionally folks might need to turn it off for a specific form.#2021-05-2518:46borkdudeand even if you enable the rule, you can ignore on a case by case basis using #_:clj-kondo/ignore#2021-05-2518:47borkdudeso, feel free to make an issue for this with some proposals, etc and we can take it from there#2021-05-2604:06d5phi, is it possible to somehow exclude unused namespace/unused referred var warnings just for a certain namespace , we use mount and have a core ns that refers to a few to ensure they load , so would like to exclude these warnings just in that ns#2021-05-2604:28seancorfield@d5p How exactly are you requiring those namespaces? What exact syntax are you using?#2021-05-2604:30seancorfieldI think that if you (:require [some.namespace]) like that rather than (:require some.namespace) that clj-kondo won't warn about it being otherwise unused?#2021-05-2604:30d5pi’m requiring them like#2021-05-2604:30d5p
(ns taskmanager.core
  (:require [taskmanager.batch.alerts :refer [task-alert-consumer]]
            [taskmanager.batch.batch :refer [batch-task-consumer incoming-batch-task-consumer]]
            [taskmanager.config :refer [project config]]
            [taskmanager.http :refer [http-server]]
            [taskmanager.db :refer [*db*]]
            [taskmanager.redis-client :refer [*redis-client*]]
            [taskmanager.queue :refer [sqs-buffered-client]])
  (:gen-class))
#2021-05-2604:30d5pand it reports all of them as unused#2021-05-2604:31seancorfieldBecause you're not using any of the referred symbols?#2021-05-2604:31d5pyeh, they’re just required in this ns to ensure mount can start them#2021-05-2604:31seancorfieldTake the :refer's out.#2021-05-2604:31seancorfieldif you're not using the symbols that is why you're getting warnings.#2021-05-2604:35d5pha , was hoping it would be something dumb and easy, and can’t get easier than that! been explicitly referring the states for years and never really thought about it, thanks!#2021-05-2617:01Adam HelinsIn hooks, what is the rationale for dealing with the clj-rewrite structures instead of taking and returning raw Clojure forms? Is is just for performance? Not complaining or anything, just thinking about linting Convex Lisp (very similar to Clojure) and wondering about what you really gain by keeping that kind of AST.#2021-05-2617:15borkdude@adam678 The reason is preservation of information mostly#2021-05-2617:16borkdudewhen I wrote the hooks stuff, I did try to make it look like normal macroexpansion, but this didn't work out as you would lose too much location information, e.g. when you transform a body that contains numbers, strings, etc#2021-05-2617:16borkdudeso I decided to expose the structure that clj-kondo itself uses#2021-05-2617:16borkdudeand by now rewrite-clj is a pretty solid library in the clj ecosystem#2021-05-2617:24Adam HelinsNow that you mention it, it's true there is quite a lot you could loose by using sexprs only, depending on use case 👍#2021-05-2717:55borkdudeI deleted borkdude/babashka and borkdude/clj-kondo on Dockerhub now. Let's see how many questions I will get and how many CIs will break... tl;dr: use babashka/babashka and cljkondo/clj-kondo#2021-05-3111:02emak☝️ it broke the GH actions in our repo :) BTW thanks for this awesome tool!#2021-05-2718:24borkdudeThere we have the first one @thiagokokada :)#2021-05-2718:26kokadaThat was fast 😆#2021-05-2720:39Felipe MarquesHi, everyone, I'm getting a weird error on clj-kondo for a file:
test/integration/enrollment_view/primary_inclusion_flow.clj:1:1: error: Unresolved symbol:
After running:
clj-kondo --cache false --lint test/integration/enrollment_view/primary_inclusion_flow.clj
I even changed the content of the file to a file that is not failing, but I keep keeting this error. Did anyone have a similar problem?
#2021-05-2720:45Felipe MarquesIt was the UTF-8 BOM character 😅 Solved by changing the encoding.#2021-05-2720:45Felipe MarquesNervermind! 😅#2021-05-2721:10Joshua SuskaloIs there any way for me to configure the :use linter to not complain about a particular ns? In this case, we like including all the specter vars with refer-all, but if we manually use (:require [com.rpl.specter :refer :all]) it says unresolved symbol on all the uses#2021-05-2721:12borkdude@suskeyhose these unresolved symbols should go away when linting the used namespace as well#2021-05-2721:13borkdudeif specter uses standard clojure to define those var and not some defcustom macro#2021-05-2721:13Joshua SuskaloAh, I see. Then I wonder why it has unresolved symbol if we put the ns in the require block but not in the use block.#2021-05-2721:15blak3mill3rit is all defnav#2021-05-2721:15borkdudecan you explain what you mean by the latter?#2021-05-2721:15blak3mill3rin specter#2021-05-2721:15borkdudeyou can solve that using :lint-as#2021-05-2721:15blak3mill3rif we put it in (:use [com.rpl.specter]) then there are no complaints about unresolved symbols from specter#2021-05-2721:16blak3mill3rbut with (:require [com.rpl.specter :refer :all]) kondo cannot resolve the symbols from specter#2021-05-2721:16borkdudeah I see what the problem is. when using :refer :all clj-kondo will go out to the cache and see if this info is already there, to give more accurate linting#2021-05-2721:17borkdudebut if specter using defnav then clj-kondo hasn't saved these vars to the cache#2021-05-2721:17borkdudeand so you will get less precise linting#2021-05-2721:17blak3mill3rgot it, that makes sense#2021-05-2721:17Joshua SuskaloI tried using lint-as and it didn't appear to fix it, but maybe I need to do something to run it without the cache#2021-05-2721:17borkdude@suskeyhose you need to re-lint specter after the config change#2021-05-2721:20Joshua SuskaloSo that'd just be by running
clj-kondo --dependencies --lint "$(clojure -Spath)"
right?
#2021-05-2721:20borkdudecorrect. use --parallel too for higher speed#2021-05-2721:21Joshua Suskalookay, cool#2021-05-2721:23borkdudeif specter would package a clj-kondo config in the jar, then you would also get a copy of that in your .clj-kondo and this way of linting would tell you how to activate that#2021-05-2721:24borkdudePerhaps you could suggest this to the specter author, if you find a config that works well: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-05-2721:31borkdudeso did it work out now @suskeyhose?#2021-05-2721:32Joshua SuskaloNo, and I'm not quite sure why. I set it to lint the defnav calls as defn, (like this https://github.com/redplanetlabs/specter/blob/master/src/clj/com/rpl/specter.cljc#L715-L723), but it's still unable to resolve those symbols.#2021-05-2721:32borkdudedid it say something about skipping already linted jars?#2021-05-2721:33Joshua SuskaloI was able to validate that it refreshed the cache because some of the symbols it hadn't recognized before it did recognize this time.#2021-05-2721:33Joshua Suskalojust not the defnav ones#2021-05-2721:34borkdudecan you post your config? also to be sure, just rm -rf .clj-kondo/.cache and try again#2021-05-2721:34Joshua SuskaloI'll try removing the cache and retrying. The whole config is just
{:lint-as {com.rpl.specter/defnav clojure.core/defn}}
#2021-05-2721:35Joshua SuskaloThis is the first time we've used a linter on this project, trying to adopt it.#2021-05-2721:36borkdudeclj-kondo just has a hard time with :refer :all and custom def macros#2021-05-2721:37borkdudeit also suggest trying not to use :refer :all (for this reason, but also for other reasons, just as a general style recommendation)#2021-05-2721:38Joshua Suskalooh boy, now it doesn't work in the use block either 😂#2021-05-2721:38Joshua SuskaloYeah, this is just unfortunate. In any case I'd still be curious if we could customize the :use linter to not complain for particular namespaces.#2021-05-2721:38blak3mill3rwe avoid :refer :all like the plague, with the one exception of specter#2021-05-2721:39blak3mill3rbecause that's a lot of short & common symbols that we do not want to prefix with s/#2021-05-2721:39borkdudeit would be good to have a repro of this, because I think it should work#2021-05-2721:39Joshua SuskaloI'll see if I can make a tiny thing that reproduces the error.#2021-05-2721:44borkdudeI will take a look tomorrow and will call it a day, it's getting close to midnight here.#2021-05-2721:44blak3mill3rmany thanks @borkdude#2021-05-2721:51Joshua Suskalohttps://github.com/IGJoshua/specter-kondo-repro#2021-05-2721:52Joshua SuskaloOh that's funny, it thinks it's C++#2021-05-2721:53Joshua SuskaloI forgot to remove the .cpcache, but whatever#2021-05-2721:57borkdude@suskeyhose I think I see the issue. The defnav macro, in .clj at least, is a locally defined using another macro. In cljs it works differently.#2021-05-2721:57borkdudeso it probably needs another lint-as for this#2021-05-2721:57borkdude
defmacroalias defnav macros/defnav
#2021-05-2721:57Joshua SuskaloRight, but if I have it lint-as defn, wouldn't that remove the issue? It seems odd that I'd have to change how defmacroalias is linted too#2021-05-2721:59borkdudeyep, that's it:
{:lint-as {com.rpl.specter/defnav clojure.core/defn
           com.rpl.specter/defmacroalias clojure.core/def}}
this works
#2021-05-2721:59Joshua SuskaloOkay, cool. Well I'll go for that. Thanks!#2021-05-2722:01borkdudeFeel free to contribute the config here: https://github.com/clj-kondo/config once you have it all working#2021-05-2722:01borkdudeOr perhaps in the specter repo itself: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-05-2722:02blak3mill3rExcellent! I have a feeling that a lot of specter users do refer all the symbols... contributing this kondo config to specter might make sense#2021-05-2722:04Joshua SuskaloSounds good, I'll look at making a PR in specter#2021-05-3009:56Adam HelinsI get this error:
gen.cljc:1:57: error: Invalid digit ` in unicode character.
Which is weird since I use ` a lot and it has never complained + there is actually nothing on 1:57
#2021-05-3009:58Adam HelinsAnd it complains even if I delete all ` from the namespace#2021-05-3010:02borkdudenever seen that error before#2021-05-3010:02borkdudeperhaps you're loading hooks?#2021-05-3010:03borkdudeset aside your clj-kondo config to be sure it's nothing related to that#2021-05-3010:06Adam HelinsNot it... I don't know when it appeared. I must have changed something and it somehow confused the linter. But the namespace compiles and works well#2021-05-3010:10borkdudemaybe try setting aside your entire .clj-kondo dir including the cache#2021-05-3010:11Adam HelinsAlright, I got it I think. On a completely different line I have this docstring:
"Any valid character for hexadecimal notation, from `\0` to  `\f`."
#2021-05-3010:12Adam HelinsI mean, this is problematic:
`\0
`
#2021-05-3010:13borkdudedo you think clj-kondo should accept it, hence a false positive?#2021-05-3010:16Adam HelinsIt is a false positive, I was trying to highlight \0 in markdown for documentation but it thinks I am trying to write a unicode char \0`#2021-05-3010:16Adam HelinsBut it's very specific, I wouldn't worry too much about it, it's just puzzling when it happens#2021-05-3010:17borkdudefeel free to post an issue, it might be a rewrite-clj specific thing#2021-05-3010:17borkdudeor tools.reader#2021-05-3010:34Adam HelinsHmmm, I am sure I am right with that \0 unicode thing (since error goes away) yet I can't reproduce it in a minimal ns. Must be some kind of weird interaction. I can't share publicly this namespace. But it's probably an exceptional case, so no big deal at all.#2021-05-3120:09borkdudeclj-kondo v2021.05.31 https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#v20210531#2021-06-0110:58delaguardoI see a warning thrown for completely normal spec
echo '(ns user (:require [foo.common :as common] [clojure.spec.alpha :as s])) (s/def ::x (s/keys :req-un [::common/x]))' | clj-kondo --lint -
<stdin>:1:21: warning: namespace foo.common is required but never used
linting took 21ms, errors: 0, warnings: 1
I think it happens because s/def expands to something like that:
... :req-specs '[:foo.common/x] ...
#2021-06-0110:58borkdudethis is a bug introduced by a new feature which has already been fixed on master#2021-06-0110:58borkdudeI can make a new release since this is annoying#2021-06-0110:58delaguardonot really#2021-06-0110:58borkdudebut maybe I'll wait a day in case there are any other regressions#2021-06-0110:59delaguardoI can wait until next release ) thanks!#2021-06-0110:59borkdudeif there will be a third person reporting this, I'll make a release ;)#2021-06-0110:59borkdudeyou were the second#2021-06-0110:59delaguardo)) reasonable enough#2021-06-0112:58wilkerlucio@borkdude third person here #2021-06-0112:59borkdudereleasing#2021-06-0113:11borkdudedone#2021-06-0113:16wilkerlucioconfirmed the lint runs good in the latest version 👍#2021-06-0116:08Joshua SuskaloHey, I'm playing around with hooks in another project and it seems like they're just not getting run at all. As far as I can tell the only difference is that I've got them directly in the .clj-kondo directory rather than inside an exports section. I'm using the binary release on the AUR from today. Is there anything I have to do to make sure it actually tries to run it?#2021-06-0116:10borkdude@suskeyhose It depends on your config. What do you have in {:hooks {:analyze-call ...}}#2021-06-0116:14Joshua Suskalo
{:hooks {:analyze-call {noah.transformer/deftransformer hooks.noah/deftransformer}}}
#2021-06-0116:15Joshua Suskalothen in that directory there's a hooks directory with the noah.clj file in it which has a deftransformer function#2021-06-0116:15Joshua Suskalo(this is working on adding hooks to the noah library, which is a clojure wrapper for kafka streams)#2021-06-0116:15borkdudedo you have a file in a directory noah/transformer.clj in the local .clj-kondo dir?#2021-06-0116:16borkdudesorry, my bad, hooks/noah.clj#2021-06-0116:16Joshua SuskaloYeah#2021-06-0116:16Joshua Suskaloit's where the hook function is#2021-06-0116:16borkdudecan you make some deliberate typos in this file to see if it crashes or something#2021-06-0116:17borkdudeor add some printlns#2021-06-0116:17borkdudeand call it from the command line#2021-06-0116:17Joshua SuskaloI have a println at the top of it before I do any code#2021-06-0116:17borkdudestick the println inside your function#2021-06-0116:17Joshua SuskaloYup, that's where it is#2021-06-0116:17Joshua Suskalo
(defn deftransformer
  [{:keys [node]}]
  (println "Being run!")
  (let [[name & more] (rest (:children node))
        [_docstring store-names & more]
        (if (api/string-node? (first more))
          more
...
#2021-06-0116:18borkdudedo you have a ns form at the top?#2021-06-0116:18Joshua SuskaloYup#2021-06-0116:19Joshua SuskaloI was observing similar behavior when I was working on farolero, except I could fix it by swapping the key in the analyze-call map for one that used a . rather than a fully-qualified symbol, like farolero.core.restart-case instead of farolero.core/restart-case, but this doesn't fix the issue here.#2021-06-0116:19borkdudewell, you're welcome to make a small repro#2021-06-0116:19Joshua SuskaloThe difference between this one and that one was that in that one I was doing --copy-config on every call to get it out of the resources directory#2021-06-0116:19Joshua SuskaloAlright, I'll try for it#2021-06-0116:20Joshua SuskaloHonestly since everything that I'm actually working on is OSS I can just extract it from the containing repo and it should work the same#2021-06-0116:22borkdudesure#2021-06-0116:33Joshua SuskaloDang it, I move it over to a small reproduction case and it runs.#2021-06-0116:34Joshua SuskaloAt least this gives me a chance to debug the hook and make it work right, then I can try and figure out why it wasn't being run in the bigger project.#2021-06-0116:34borkdude:thumbsup:#2021-06-0116:46Joshua SuskaloWhat am I supposed to use for a map node in the resulting code?#2021-06-0116:47borkdudeoften just (token-node nil) works#2021-06-0116:47Joshua SuskaloHmm. Alright.#2021-06-0116:48borkdudeSo far I haven't seen a single case where hooks should actually create a map. In the future this might be possible, but the API doesn't allow it right now because the API in rewrite-clj around this wasn't very stable yet#2021-06-0116:50Joshua SuskaloFair enough.#2021-06-0117:23Joshua SuskaloIs there any way that I can suppress unused-symbols for particular symbols in sections of code produced by a hook?#2021-06-0117:36Joshua SuskaloLike there's some code that's got an unhygenic macro, so there's some let blocks that have symbols that may or may not be used in the body, and I don't want it to emit warnings either way.#2021-06-0117:45Joshua SuskaloOh btw, one place you'll need a map node is if someone wants to emit a with-bindings call. Sure, technically you could also emit a bindings call, but it'll technically be incorrect because if you emit bindings then ordering matters and previously-seen bindings will be assumed to be used in later ones, making certain classes of lints that pay attention to the values attached to bindings impossible.#2021-06-0117:48Joshua Suskalo(I figured out why it didn't run in the bigger project, I accidentally called it config.clj rather than config.edn)#2021-06-0118:01Joshua SuskaloOkay, looks like I can emit a comment node in order to ignore the unused binding warning on the unhygenic macro
#2021-06-0118:07Joshua SuskaloOnly issue is that I can't import the namespace which exposes comment nodes#2021-06-0118:09Joshua Suskalo@borkdude do you have any suggestions for this?#2021-06-0119:56borkdude@suskeyhose > Is there any way that I can suppress unused-symbols for particular symbols in sections of code produced by a hook? Yes, you can start the symbol names with underscore, (gensym "_")#2021-06-0119:58borkdudeor you can just emit code that uses them#2021-06-0120:00Joshua SuskaloThat doesn't exactly work for making hooks for unhygenic macros though.#2021-06-0120:02borkdudeoh you said unhygienic :) well, I guess you can generate:
(let [x ..] x ...)
?
#2021-06-0120:03Joshua SuskaloOh.#2021-06-0120:03Joshua SuskaloWhy didn't I think of that#2021-06-0120:03Joshua SuskaloThanks!#2021-06-0120:11borkdudewhy do you want to generate something with with-bindings btw? afaik clj-kondo doesn't really have any special linting around this#2021-06-0120:11borkdudethe generated code doesn't really have to reflect the original macro, as long as the input nodes are used in a way that makes sense for linting#2021-06-0120:28Joshua SuskaloI actually don't have anything in particular about with-bindings that I want to generate, I was just pointing out that certain classes of linters (which you may or may not ever want to implement) would be impossible to represent atm because we lack a concept of unordered bindings, which with-bindings has.#2021-06-0120:29borkdudeTrue. Eventually we will get it, but afaik there is no reason to specifically emit this for any reason#2021-06-0120:30borkdudeunless there is some linter checking that "with-bindings must be used because this and that"#2021-06-0120:31Joshua SuskaloFair enough.#2021-06-0214:01Joshua SuskaloSo I'm looking at the codebase to try and add an exclude config to use blocks. It looks like the :use lint is different from the other ns lints in that it's registered immediately rather than just associng in something new to register a finding for later. For this would it be better to try and refactor the use finding to work the same way as e.g. refer-all, or would it be better to just add an additional requirement in the and expression that gates registering the finding?#2021-06-0214:02Joshua SuskaloThe latter is most certainly easier, but it's inconsistent with the rest.#2021-06-0214:05borkdudeWhat is the problem you're trying to solve?#2021-06-0214:07borkdudeyou're trying to unify the code for :use and :refer :all in clj-kondo's codebase?#2021-06-0214:07Joshua SuskaloMore or less. I just want the :use linter to have an :exclude config#2021-06-0214:08borkdudeyou could also migrate to :refer :all#2021-06-0214:08borkdudebut that's only a workaround ;)#2021-06-0214:09borkdudebut I'm open to improvements, as long as the tests pass and there are no perf regressions#2021-06-0214:09Joshua SuskaloYeah.#2021-06-0214:10Joshua SuskaloRight. I was more or less asking if you'd prefer if I just add a one-liner that just doesn't register the use finding if the config excludes the ns, or if you'd prefer that I try to make use work like refer does#2021-06-0214:11borkdudeI would have to look into that, don't remember the exact code. I think :refer :all has some logic that prefetches some vars from the cache to improve linting, does :use also have that?#2021-06-0214:15Joshua Suskaloyeah, looks like there's a call to reg-var-usage!#2021-06-0214:20borkdudeI actually meant this part: https://github.com/clj-kondo/clj-kondo/blob/2bfc8bfe50d143f5806f489a074ff601ab834a16/src/clj_kondo/impl/analyzer/namespace.clj#L221-L226#2021-06-0214:20borkdudeWhat it does is look at the cache in case of :refer :all so it can actually resolve names better. clj-kondo has a hard time with use and refer all because it has nothing to go by statically#2021-06-0214:20Joshua Suskaloit just assoces stuff into the :referred-all segment and passes that on so that it would get used here#2021-06-0214:25R.A. PorterI don't know if this is a problem with Cursive, the IJ file watcher plugin, or clj-kondo, but I'm seeing the following, where the indicator in the IDE is highlighting the fn inside the sexpr instead of either the whole sexpr or the int fn itself (what I'd expect). The output below shows the correct columns, which correspond to the open paren for the subs sexprs.#2021-06-0214:26borkdudecan you make a minimal repro in text? then I'd be happy to try out what it does in emacs. you could also just disable clj-kondo to see if that is or is not the problem?#2021-06-0214:45R.A. PorterThis function does it for me:
(ns alignment)

(defn foo
  [s]
  (let [sub1 (subs s 0 10)
        x (int (subs sub1 0 2))
        y (int (subs sub1 3 5))]
    (+ x y)))
#2021-06-0214:45R.A. PorterWith clj-kondo turned off, it doesn't highlight the subs fns; with clj-kondo turned on, it does.#2021-06-0214:48borkdudeThe reason it highlights it is that subs returns a string but int expects a char, although in CLJS that may just work #2021-06-0214:50R.A. PorterMy expectation is that it would highlight either int or the entire function call for subs if that's not what is intended, I'll just have to adjust my expectation.#2021-06-0214:51borkdudeI’ll try in emacs when I get back to home#2021-06-0215:28borkdudeI think it's just an artifact of how the tooling works, clj-kondo does the right thing I think#2021-06-0215:04Joshua Suskalohttps://github.com/clj-kondo/clj-kondo/pull/1290#2021-06-0215:30borkdude@U5NCUG8NR feedback: this kind of stuff:
(set (get-in ctx [:config :linters :use :exclude])
is done in config.clj in a way that it caches this result
#2021-06-0215:30borkdudeI mean, getting values from the config#2021-06-0215:31Joshua SuskaloOh, cool. I'll try taking a look at that. This is why I wanted to make it a draft, so I'd find some things that I wouldn't have thought of otherwise. 🙂#2021-06-0215:33Joshua SuskaloThat's interesting, it looks like all the other config access in this file is just threading it through keywords#2021-06-0215:34borkdude?#2021-06-0215:37Joshua Suskalohttps://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/namespace.clj#L36#2021-06-0215:37Joshua SuskaloBut maybe I'm missing something here and the caching happens earlier, looks like it does in the linters.clj file#2021-06-0215:38borkdudein config.clj#2021-06-0215:38borkdudeas I said#2021-06-0215:38borkdudethe above are just checks whether the config is enabled or not#2021-06-0215:39Joshua SuskaloRight, I was looking for usages of it.#2021-06-0215:39borkdudebut sometimes more work is needed, such as the set conversion you are doing#2021-06-0215:39borkdudeand this should optimally only happen once#2021-06-0215:40borkdudebut as people can also have namespace-local config, this should be cached per version of the config#2021-06-0215:40Joshua SuskaloAh, makes sense. I did make a coersion function there. Actually, I'm looking at this and it appears that there may be a bug/feature which is that the config for refer-all appears to apply to both use and refer-all#2021-06-0215:40borkdudethat may just be a feature#2021-06-0215:41Joshua SuskaloThen this pr should probably just update the documentation#2021-06-0215:41borkdudenice#2021-06-0215:44Joshua SuskaloI think it's a little weird that there's two different linters and yet only one configuration, but if this is fine, then I'll just update the docs.#2021-06-0215:45borkdude:refer :all and :use are very similar in their effect#2021-06-0215:46borkdudewhether you write (:use clojure.test) or (:require [clojure.test :refer :all]) shouldn't matter#2021-06-0215:46borkdudeif you want to ignore one, you probably want to ignore the other too#2021-06-0215:46Joshua SuskaloYeah, I agree with you, but it just seems weird that there's two different linters for it then.#2021-06-0215:47borkdudenot sure why that was again, but clj-kondo tries to discourage the use of both as you get worse linting with it anyway.#2021-06-0215:48borkdudeI personally never use either#2021-06-0215:48Joshua SuskaloThat's definitely fair. I don't under normal circumstances.#2021-06-0215:48borkdudethere are exceptions like DSL-like things#2021-06-0215:50Joshua SuskaloYup. In any case, the PR is updated, it only adds a config section to the use linter which refers back to the refer-all linter#2021-06-0215:51borkdudemerged#2021-06-0215:51Joshua SuskaloAwesome, thanks#2021-06-0219:19Joshua SuskaloDoes the lint-as clojure.core/defn have issues with multiple fn bodies?#2021-06-0219:23borkdudeit should not#2021-06-0219:27Joshua SuskaloHmm. I'm trying to mess with specter again and multi-path isn't linting correctly. I've set the lint-as for defdynamicnav to lint-as defn, but it's saying it can't resolve path1 and path2
(defdynamicnav multi-path
  "A path that branches on multiple paths. For updates,
   applies updates to the paths in order."
  ([] STAY)
  ([path] path)
  ([path1 path2]
   (late-bound-richnav [late1 (late-path path1)
                        late2 (late-path path2)]
     (select* [this vals structure next-fn]
       (let [res1 (i/exec-select* late1 vals structure next-fn)]
         (if (reduced? res1)
           res1
...
#2021-06-0219:28borkdudecan you make an example I can actually try locally, so a complete form? this will make it easier for me to help you#2021-06-0219:28Joshua SuskaloSure, sorry about that#2021-06-0219:29Joshua Suskalo
(defdynamicnav something
  "blah"
  ([] nil)
  ([path] path)
  ([item1 item2]
   [item1 item2]))
#2021-06-0219:29Joshua SuskaloThis recrates the error, all defdynamicnav has to be is some random macro that has lint-as set to defn#2021-06-0219:30Joshua SuskaloHmm. It seems like it might be something specific to this config. I want to do a little more testing.#2021-06-0219:30borkdudeThis works:
(ns foo
  {:clj-kondo/config '{:lint-as {bar/defdynamicnav clojure.core/defn}}}
  (:require [bar :refer [defdynamicnav]]))

(defdynamicnav something
  "blah"
  ([] nil)
  ([path] path)
  ([item1 item2]
   [item1 item2]))
#2021-06-0219:31Joshua SuskaloYeah, it worked fine for me just now too when I defined my own macro. Maybe it's that defdynamicnav is being created wrong or something.#2021-06-0219:31Joshua SuskaloI need to go through this a little more slowly.#2021-06-0409:53slipsetCould this be linted?
(defprotocol Bar
  (bar [_ x]))

(defrecord foo [x]
  Bar)

(bar (->foo 1) 1) ;; explodes
So basically a warn (or error) on missing implementation of protocol-fn?
#2021-06-0410:06borkdudeI think it could#2021-06-0413:14Karol WójcikI think I found a false positive with clj-kondo. something.cljc
(let [lname "hello-world"
      gfullname #?(:bb nil
                   :clj (symbol (str (ns-name *ns*) "." lname)))
      gclass #?(:bb nil
                :clj (println gfullname)
                :cljs nil)])
❯ clj-kondo --lint something.cljc     
something.cljc:1:6: error: let binding vector requires even number of forms
something.cljc:1:7: warning: unused binding lname
something.cljc:2:7: warning: unused binding gfullname
something.cljc:4:7: warning: unused binding gclass
something.cljc:4:7: error: Unresolved symbol: gclass
something.cljc:6:23: error: unsupported binding form nil
linting took 35ms, errors: 3, warnings: 3
Can someone reproduce it as well? clj-kondo v2021.05.31
#2021-06-0520:45dominicmBtw, you can use :default to target (not :clojure): #?(:clj (symbol …) :default nil)#2021-06-0413:18borkdudehave you tried to run it? ;)#2021-06-0413:18borkdudeespecially in CLJS it should not work#2021-06-0413:18borkdude
cljs.user=> (load-file "/tmp/something.cljc")
Unexpected error (ExceptionInfo) macroexpanding cljs.core$macros/let at (<cljs repl>:1:1).
let requires an even number of forms in binding vector
#2021-06-0413:20Karol WójcikOh 😂 My bad! I have tried java/bb 😄#2021-06-0413:21borkdudedo you want to run this file in CLJS as well btw?#2021-06-0413:21Karol WójcikIn some time probably yes#2021-06-0413:22borkdudeok#2021-06-0414:18borkdude@slipset feel free to create an issue#2021-06-0414:47slipsetWill do!#2021-06-0512:31Adam HelinsThere must be something obvious I can't see. I can't get to import the config of a lib I've written. I know it is on the classpath, I see it in the lib jar under "clj-kondo.exports/io.helins/mprop/config.edn". I run the same import command as in the doc. I know this jar is present since I can see it is being linted. Something wrong with the path?#2021-06-0512:34borkdude@adam678 How did you "import" the config? clj-kondo --lint $(clojure -Spath) --dependencies ?#2021-06-0512:35Adam Helins
clj-kondo --copy-configs --dependencies --lint "$(clojure -Spath)"
Yes, copy/pasted this line from https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md
#2021-06-0512:36borkdudeoh right, and you didn't see the output similar to "copied config to ..." ?#2021-06-0512:36borkdudedo you have a local .clj-kondo directory?#2021-06-0512:36Adam HelinsNo, and indeed nothing is copied to ./.clj-kondo 😞#2021-06-0512:36Adam HelinsYes#2021-06-0512:37borkdudeis this library public? I can try it myself#2021-06-0512:37borkdude(be back later)#2021-06-0512:39Adam HelinsAlmost public#2021-06-0512:40borkdudeis it a git dep or jar dep#2021-06-0512:42Adam HelinsI've installed it locally (so jar dep)#2021-06-0514:14Adam HelinsActually I am doing something wrong at import. I can't reproduce the clj-kondo/config example. Weird... I never had this problem. It's in my deps, on my classpath, and I have a .clj-kondo directory with proper R/W access...#2021-06-0514:16Adam HelinsAll I get is a long list of errors + warnings from and it ends like this without any copying done:
linting took 2750ms, errors: 132, warnings: 433
#2021-06-0514:26Adam HelinsOkay, I feel ashamed. All this fuzz has been solved... by an update of Clj-kondo. I still have no idea what went wrong though.#2021-06-0514:30borkdudecool!#2021-06-0514:31borkdudeno need to be ashamed, glad it's solved#2021-06-0514:38Adam HelinsAlways makes me think of IT Crowd's "Did you try turning it off and on again..." when something like that happens. Anyways, have a nice WE!#2021-06-1110:40pedrorgirardiI'm slowly building my Clojure setup on Sublime Text based on clj-kondo and it's been a super fun experience! But since I'm doing everything based on the analysis output, I don't have a REPL to do anything, and now I'm wondering how to get the location of a file which is in my classpath e.g.: clojure/core.clj. In a Clojure REPL we could ( "clojure/core.clj"), but...I don't have a REPL. How would you do it?#2021-06-1110:42pedrorgirardiI need to know the path of the file so I can implement a Go to... type of thing.#2021-06-1110:42borkdudeThe analysis includes the locations of files, right?#2021-06-1110:42pedrorgirardiThis 'filename': 'clojure/core.clj',#2021-06-1110:42pedrorgirardiNot the full path.#2021-06-1110:42pedrorgirardiAm I missing something?#2021-06-1110:43pedrorgirardi#2021-06-1110:44borkdude@pedrorgirardi Ah, this is a bit hidden, here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#output-canonical-file-paths#2021-06-1110:45pedrorgirardiOhh,,this is great!#2021-06-1110:45pedrorgirardiThanks @borkdude!#2021-06-1110:45borkdudeWelcome. Keep us posted about your cool project :)#2021-06-1110:50pedrorgirardiIt's amazing what you can do based on clj-kondo's analysis output. It's really good! 🙂 I started working on this for myself, I would like to use Sublime Text to program in Clojure, but maybe it could be something others could use too. It's very early days still, so we will see.#2021-06-1110:53pedrorgirardiAnother question. I do the initial setup to create a clj-kondo cache and all. But then, I have a Sublime Text command to analyze the classpath which I use to "index" var definitions & usages. I'm currently running with these options whenever I want to analyze the classpath:#2021-06-1110:53pedrorgirardi#2021-06-1110:53pedrorgirardi(It's Python)#2021-06-1110:53pedrorgirardiIs this the way to go?#2021-06-1110:55borkdudeyes, that looks good. if you analyze everything, you don't have to do anything else before it, except to create a .clj-kondo directory.#2021-06-1110:57pedrorgirardiRight, I got you.#2021-06-1111:31martinklepschis there a way to disable redefined-var warnings inside comment blocks?#2021-06-1111:50borkdudein general or one specific comment block?#2021-06-1111:50martinklepschin general#2021-06-1111:52Adam Helinsor similarly, unresolved in (comment) ?#2021-06-1111:53borkdudeyou can turn off all linting in comment forms with {:skip-comments true}#2021-06-1111:56borkdudePerhaps we should disable the redefined-var linter in the comment form by default as I can't come up with a reason why this would be unreasonable to do.#2021-06-1112:04borkdude@adam678 Your issue can be solved with:
$ clj-kondo --config '{:linters {:unresolved-symbol {:exclude [(clojure.core/comment)]}}}' --lint - <<< '(comment a b)'
linting took 11ms, errors: 0, warnings: 0
#2021-06-1112:05borkdude@martinklepsch Feel free to post an issue about this.#2021-06-1112:07martinklepsch@borkdude wouldn’t the approach above work for redefined var too?#2021-06-1112:07borkdudeyeah, we could implement that as well#2021-06-1112:08borkdudebut it's a bit weird to do this for vars, since they are usually defined top level and not inside some other call#2021-06-1112:08borkdudeso comment is a bit of a special case#2021-06-1112:09borkdudelet's just make an issue for it and then think about the right config later#2021-06-1112:10borkdudeI would be fine with just disabling the redefined var linter inside comment blocks#2021-06-1112:11martinklepsch👍 https://github.com/clj-kondo/clj-kondo/issues/1294#2021-06-1113:27Matt ButlerHey, everyone 🙂 Sorry if I've missed it, but is there a way to blanket ignore a namespace?#2021-06-1113:46borkdude@mbutler you can do it like this: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#include-and-exclude-files-from-the-output#2021-06-1114:07Matt ButlerAwesome, thanks man :)#2021-06-1306:35robert-stuttafordit looks like with :skip-comments true at the project level, and :skip-comments false at the namespace level, unused requires doesn't see the usages inside comment forms in our dev/*.clj repl scripts, and continues to warn about unused namespaces when they are actually used inside the comments. (we skip comments on the project level as we have a pre-commit hook to prevent committing anything with linter warnings or errors) when i set false at the project level, it does see them, and stop warning about unused requires. by no means a showstopper, just wondering if this is something that is simple to fix, or inherent to the way the usage analysis is working?#2021-06-1308:22borkdudeI can reproduce the issue locally.#2021-06-1308:47robert-stuttafordok, so it's not just me 😄 thank you @U04V15CAJ!#2021-06-1410:11borkdude@U0509NKGK Fixed on master. You could use a versioned snapshot version if you are using clj-kondo on the JVM in CI.#2021-06-1410:11borkdudeWhat I mean is: > Sending clj-kondo/clj-kondo/2021.06.02-SNAPSHOT/clj-kondo-2021.06.02-20210614.101046-4.jar (309k)#2021-06-1410:11borkdudeyou could use the "2021.06.02-20210614.101046-4" part as the version#2021-06-1410:21robert-stuttafordthank you @U04V15CAJ!#2021-06-1405:21maxpcould someone help me with correct :lint-as for http-kit
(with-channel request channel
   ....
)
which defines symbol channel
#2021-06-1408:16borkdude@maxp I don't think there is one. Most binding macros use vectors for their bindings#2021-06-1408:26tatutI’ve had similar problems with my own macros as well… if you could give a clojure expression to get the symbols, that would be great#2021-06-1408:27tatutdon’t know if that’s feasible#2021-06-1408:28borkdudeClj-kondo allows you to write hooks that allows you to support basically any macro.#2021-06-1408:28tatutgreat! I’ll need to check it out#2021-06-1408:28borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-06-1408:29borkdudeThese hooks can be packaged along with your libraries so other people will automatically receive them when they lint your library#2021-06-1604:46tatuttried hooks and it works great, transformed my custom macro into a simple defn that can be linted#2021-06-1605:00tatutthe map-node seems to be commented out in the hooks api#2021-06-1607:04tatutlittle cumbersome to develope without repl, should probably start a clj-kondo repl in jvm clojure for hook development#2021-06-1607:05borkdude@tatut you can use prn and println :)#2021-06-1607:06borkdudebut yeah, you can also run clj-kondo on the JVM and then run the hook over some code#2021-06-1607:06tatutyeah, tried that but I found it still difficult to determine what I can do with the ndoes#2021-06-1607:06tatutI’m used to “inspect things in the repl” workflow so println is painful 😄#2021-06-1611:59tatutah, but the hooks api is not in the jvm version… it’s a sci thing?#2021-06-1612:01borkdude@tatut correct. it runs in sci for both safety and native-image compatibility (can't use clojure's eval in a native binary)#2021-06-1709:12niwinzHello, One question, maybe is obvious and is documented somewhere but I didn't found it: how can I disable linting for a concrete namespace, from the namespace file (probably using namespace metada)?#2021-06-1709:16niwinzI just want to disable all linters for few files, using config file or namespace metadata#2021-06-1709:17borkdude@niwinz You can use https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#include-and-exclude-files-from-the-output#2021-06-1709:17niwinzoh, I missed it because I searched for excluding namespaces, that was not obvious hehe, thanks#2021-06-1709:24borkdudeno worries, I get the question more often#2021-06-1809:34borkdudeclj-kondo new release: 2021.06.18 New - Lint arities of fn arguments to higher order functions (`map`, filter, reduce, etc.) E.g. (map-indexed (fn [i] i) [1 2 3]) will give a warning about the function argument not being able to be called with 2 arguments. - Add map-node and map-node? to hooks API Enhanced / fixed - Disable redefined-var warning in comment - :skip-comments false doesn't override :skip-comments true in namespace config - False positive duplicate element set for symbols/classes https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#20210618 Happy linting!#2021-06-1819:12DerekAnyone know of kondo config for using test.chuck or a convenient lint-as for com.gfredericks.test.chuck.clojure-test/checking which has the form (checking "string identifier" optional-options vec-of-bindings)#2021-06-1819:14borkdude@dpassen1 doesn't ring a bell, you could write a hook for it, or ignore unresolved symbols in this macro using a config#2021-06-1819:15DerekThanks. I will look further into it#2021-06-2200:07seancorfieldDoes clj-kondo do anything with :arglists metadata or does it use the underlying argument declarations? (this is in the context of Eastwood trying to check calls using :arglists which I recall having problems with in the past)#2021-06-2200:12seancorfield(and I guess the same Q applied to LSP @ericdallo? My quick experimentation suggests that both kondo and lsp rely on the actual argument declarations and ignore the :arglists metadata?)#2021-06-2200:19ericdalloclojure-lsp totally relies on clj-kondo https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md, in this case :arglist-strs from https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#data. I'm not sure if clj-kondo fill it with that :arglists metadata#2021-06-2200:33seancorfieldThanks @ericdallo — as far as I can tell, clj-kondo ignores the :arglists metadata, based on limited experimentation. The downside is that “show hover” in Calva seems to come from LSP which therefore shows the actual argument lists rather than any doc-friendly :arglists that doc would show — but at least the linting is done correctly, which is my main concern.#2021-06-2200:38ericdalloI see, yes, you are right, I confirmed that show hover for ns clojure.core macro shows [name & references] instead of the arglists metadata '([name docstring? attr-map? references*])#2021-06-2200:39ericdallothis is the analysis data returned from clj-kondo for the ns macro:
{:end-row 5809,
  :name-end-col 13,
  :name-end-row 5753,
  :name-row 5753,
  :added "1.0",
  :ns clojure.core,
  :name ns,
  :defined-by clojure.core/defmacro,
  :filename
  "/home/greg/.emacs.d/.local/etc/workspace/.cache/clojure.core.clj",
  :macro true,
  :col 1,
  :name-col 11,
  :end-col 71,
  :arglist-strs ["[name & references]"],
  :varargs-min-arity 1,
  :doc
  "Sets *ns* to the namespace named by name (unevaluated), creating it\n  if needed.  references can be zero or more of: (:refer-clojure ...)\n  (:require ...) (:use ...) (:import ...) (:load ...) (:gen-class)\n  with the syntax of refer-clojure/require/use/import/load/gen-class\n  respectively, except the arguments are unevaluated and need not be\n  quoted. (:gen-class ...), when supplied, defaults to :name\n  corresponding to the ns name, :main true, :impl-ns same as ns, and\n  :init-impl-ns true. All options of gen-class are\n  supported. The :gen-class directive is ignored when not\n  compiling. If :gen-class is not supplied, when compiled only an\n  nsname__init.class will be generated. If :refer-clojure is not used, a\n  default (refer 'clojure.core) is used.  Use of ns is preferred to\n  individual calls to in-ns/require/use/import:\n\n  (ns foo.bar\n    (:refer-clojure :exclude [ancestors printf])\n    (:require (clojure.contrib sql combinatorics))\n    (:use (my.lib this that))\n    (:import (java.util Date Timer Random)\n             (java.sql Connection Statement)))",
  :bucket :var-definitions,
  :row 5753}
It probably should check for the :arglists metadata, right @U04V15CAJ?
#2021-06-2200:46seancorfieldWell, anything involving actually checking calls should use the actual arguments, but documentation should probably use the :arglists metadata.#2021-06-2200:47seancorfieldSo I think clj-kondo is returning the correct information there — but perhaps should also return :arglists-metadata-strs or something which clients (like LSP) could use for documentation (only)?#2021-06-2200:50ericdalloLooks good to me, then clojure-lsp could use this new field if available fallbacking to arglist-strs#2021-06-2200:50ericdalloAs we only use this field for hover documentation#2021-06-2200:50ericdalloAnd signature-help feature#2021-06-2207:52borkdudeFeel free to raise an issue about what should change (and optionally a PR)#2021-06-2217:13Joshua E CookI have a namespace of macros definitions which are required using :refer :all … is it possible to convince clj-kondo to resolve those symbols without redoing the require forms to refer to them specifically?#2021-06-2217:20borkdude@jec yes. in that case you should lint that library code as well, so clj-kondo knows about the existence of the vars.#2021-06-2217:22Joshua E CookThanks @U04V15CAJ. In my case, the macros namespace is in a dependency package. Is there a way to tell clj-kondo how to lint that code as well?#2021-06-2217:22Joshua E CookI'm trying to do this within VS Code btw.#2021-06-2217:23Joshua E CookIntelliJ + Cursive is able to resolve these macros correctly, but I'd prefer to use VS Code if I can get this to work.#2021-06-2217:24borkdude@jec Yes. This info is in the readme of clj-kondo under "Project setup"#2021-06-2217:24borkdudeThis is probably similar to how Cursive does it: the analyzer just has to see all of the code first#2021-06-2217:24Joshua E CookI think I see… you're refering to the --dependencies flag right?#2021-06-2217:26borkdudeyes. so if you use lein:
clj-kondo --lint "$(lein classpath)" --dependencies --parallel --copy-configs
#2021-06-2217:26borkdudeyou'll also need a .clj-kondo directory first#2021-06-2217:26Joshua E CookAdding that flag on the commandline seems to quiet the linter. But is there a way to set that in the config file? I'm not sure how to send that flag from VS Code#2021-06-2217:27borkdude@jec you don't need to#2021-06-2217:27borkdudeonce it has linted your dependencies, the vars are known#2021-06-2217:28borkdudeor at least should be#2021-06-2217:28borkdudebut the requirement is: you have to have .clj-kondo dir. can you confirm you have this?#2021-06-2217:29Joshua E Cookyes I have that dir#2021-06-2217:29Joshua E Cookare you saying the dependencies only need to be linted once, then the results are cached there?#2021-06-2217:29borkdudeyes#2021-06-2217:29Joshua E Cookcool ty#2021-06-2217:39Joshua E Cookwell that seems to work on the commandline but it still flags these as problems in the VS Code editor…#2021-06-2217:40borkdudeIf you can make a standalone minimal repro for that library, that I can clone locally, I could try it myself#2021-06-2217:41borkdudecould you also lint the file that gives problems in VSCode from the command line?#2021-06-2217:41borkdudejust with clj-kondo --lint src/foo.clj, no other flags#2021-06-2217:42Joshua E Cookyes, linting the single file on the commandline with no other flags is quiet#2021-06-2217:43borkdudeThen that's weird. This is an issue for #calva then. Tell them that clj-kondo on the command line works, but not in VSCode#2021-06-2217:44Joshua E Cookty, I will try over there#2021-06-2217:45borkdudeHmm come to think about it... It could be that you are using a different version on the command line than is used in VSCode. But VSCode / Calva should already have linted your deps as well btw#2021-06-2217:45borkdudeWhich library is giving problems?#2021-06-2217:45borkdudecc @U0ETXRFEW @ericdallo#2021-06-2217:47borkdudeYou could also try upgrading clojure-lsp and re-open your workspace#2021-06-2217:47borkdudeAt this point it's hard for me to give other options since it's apparently a downstream problem#2021-06-2217:53Joshua E CookOn the cli I'm using clj-kondo v2021.04.23 and in VS Code I'm using Calva v2.0.200#2021-06-2217:58borkdude@jec which library namespace is giving the unresolved vars?#2021-06-2217:59Joshua E Cook@U04V15CAJ it's not a public library, I'm working with a private codebase#2021-06-2218:00Joshua E CookI have to go now, but I will check in again later#2021-06-2218:01borkdudeok, my last advice would be to upgrade clojure-lsp and restart your project. Calva has an option to upgrade clojure-lsp.#2021-06-2218:46ericdalloYeah, I can test if it's a Calva or clojure-lsp issue if you have a minimal repro#2021-06-2219:48Joshua E Cookhey! it looks like setting Calva's version of clojure-lsp to 2021.04.23-15.49.47 matches my cli behavior#2021-06-2219:49borkdudecool#2021-06-2219:49borkdudecould you also upgrade lsp to see if it still works? you will have to restart vscode so lsp is going to lint your deps (that can take a few seconds, maybe a minute)#2021-06-2219:49borkdudeto the newest I mean#2021-06-2219:58Joshua E Cookset to 2021.06.21-14.30.54 and it isn't working for me#2021-06-2219:59borkdudeso I guess LSP isn't automatically linting your deps. Did you restart VsCode?#2021-06-2219:59ericdalloI'm not sure it's a issue with the clojure-lsp version, could you just copy the macros or make a repro with them? probably you will be able to repro the issue#2021-06-2220:00ericdalloTry to remove .lsp/sqlite.db and .clj-kondo/.cache and restart vscode#2021-06-2220:30Joshua E Cookok, lspVersion set to 2021.06.21-14.30.54, removed those databases, then restarted vscode#2021-06-2220:30Joshua E Cookit seems to be working#2021-06-2220:31ericdalloI'm not sure why sometimes there are users that complain about those kind of issues and it's solved removing those cache files, I'd like to improve that somehow, I just don't know how 😅#2021-06-2220:34Joshua E Cookmaybe because I had used a different clj-kondo version on the commandline?#2021-06-2220:36ericdalloor a old one via calva, yeah, makes sense I think#2021-06-2221:02borkdudeThe command line clj-kondo doesn't interact with Calva or LSP, so that's not the reason#2021-06-2221:04borkdudeNext time, try removing .lsq/sqlite.db first, without the clj-kondo cache#2021-06-2221:05borkdudeThen we know if it's a caching problem in lsp. If not, also remove the clj-kondo cache. Then we know it's in either lsp or clj-kondo. Then also try only removing the clj-kondo cache if the problem occurs again.#2021-06-2221:05borkdudeThat will give us more info than removing both at the same time.#2021-06-2221:05ericdalloGood idea#2021-06-2313:03Ian Fernandezhow can I ignore seq over (not (empty? for a single function?#2021-06-2313:21borkdude@d.ian.b you mean in one spot?#2021-06-2313:22Ian Fernandezyup#2021-06-2313:23Ian Fernandezon top of some s-expr with it included or something like this#2021-06-2313:24borkdude@d.ian.b put #_:clj-kondo/ignore before the s-expr#2021-06-2313:24Ian Fernandezok#2021-06-2313:24Ian Fernandezthanks @borkdude 😄#2021-06-2417:30Joshua SuskaloIn the hooks, is there a way to get access to the children of a vector node?#2021-06-2417:32Joshua SuskaloOh, nvm, I figured it out#2021-06-2417:47Joshua SuskaloDo transducers work as intended in sci?#2021-06-2417:47Joshua SuskaloI'm getting some very strange behavior#2021-06-2417:54Joshua SuskaloOh never mind.#2021-06-2417:54Joshua SuskaloI was shadowing something.#2021-06-2419:25Joshua SuskaloHey @borkdude have you thought about making the shadowed-var linter have configuration to include all the clojure vars? I'd like to turn on shadowed-var, but only for clojure.core#2021-06-2419:26Joshua SuskaloOr potentially the configuration would allow specifying namespaces, and not just individual vars.#2021-06-2419:50borkdude@suskeyhose yeah, I think specifying namespaces would be the more flexible option. For clojure.core the linters.md doc sugggests also: > To avoid shadowing core vars you can also use :refer-clojure + :exclude in the ns form.#2021-06-2419:51Joshua SuskaloYeah, I'm aware of that and use it in some of my code, but sometimes I forget that I'm shadowing core when I write something and then stuff breaks when I try to use the version from clojure core (or worse it works when I use the cider debugger because the debugger searches for vars for things in function call position even if those symbols are shadowed, but it doesn't work otherwise)#2021-06-2419:52borkdudeok, we can have :include [clojure.core] and you can unblock things with :exclude [ns] for example?#2021-06-2419:52Joshua SuskaloYeah, that looks great to me. 🙂#2021-06-2419:54borkdudehmm, that probably won't work, since :include right now expects simple symbols which are the var names that are shadowed by a binding#2021-06-2419:54borkdudeso we'll have to make a separate key for it, like :namespaces [...]#2021-06-2419:55Joshua SuskaloYeah, that makes sense, otherwise we'd have issues with single-segment nses or people who make vars with dots#2021-06-2419:55borkdudeactually only the first since you can't have bindings with dots, so you can't shadow vars with dots#2021-06-2419:56Joshua SuskaloOh interesting, I didn't know that.#2021-06-2419:56Joshua SuskaloI guess I'd never tried it before.#2021-06-2507:25dharriganI have an interesting one. I'm working on a project that has something like this (sql/defsql "filetoload.sql" :as q)#2021-06-2507:26dharriganthe sql/defsql is a defmacro that uses hugsql. I've read the helpful tips about hugsql on the wiki, but in this case it doesn't apply, since...#2021-06-2507:26dharriganthe macro does this (in its internals) (alias '~alias query-namespace#) where the alias is the q above.#2021-06-2507:27dharriganso, in the namespace, I get this:#2021-06-2507:28dharrigan(a moment, just editing file)#2021-06-2507:29dharrigan#2021-06-2507:32dharriganSo, the q is defined in the namespace as an alias. It is then used in that namespace as q/some-hugsql-thingie, but clj-kondo doesn't know anything about it.#2021-06-2507:44dharriganI've put up an example here #2021-06-2507:57borkdude@dharrigan oh man :)#2021-06-2507:57borkdudeI didn't even know hugsql could do this#2021-06-2507:57dharriganI think it's more the project I'm working on, and the way they've done it, rather than hugsql 🙂#2021-06-2507:58dharriganbut yeah....I hear you#2021-06-2507:58borkdudebut I think you could write a hook for this, shouldn't be too hard#2021-06-2507:58borkdudeand if you figure the hook out, you could contribute it to: https://github.com/clj-kondo/config/tree/master/resources/clj-kondo.exports/clj-kondo#2021-06-2507:59dharriganI'll see if I can get some time to think about how to do it#2021-06-2507:59borkdudeor perhaps you could put (comment (alias 'q ...)) in there, so clj-kondo thinks there is an alias q, but this would be a workaround#2021-06-2913:49nikolavojicic
(alias 'sn (create-ns 'some-namespace))
::sn/foo ;=> :some-namespace/foo
... Unresolved namespace sn. Are you missing a require?
#2021-06-2913:50nikolavojicicHow to avoid this warning? Note: there is no file some_namespace.clj so I can't require it.#2021-06-2913:51borkdude
(alias 'sn (create-ns 'some-namespace))
::sn/foo ;; false positive
sn/foo ;; works
yes, this seems a bug, feel free to post an issue
#2021-06-2913:52borkdudeah no, I was fooled, clj-kondo only reports the first occurrence of the unresolved namespace#2021-06-2913:53borkdudethis does seem to work:
(alias 'sn 'foo #_(create-ns 'some-namespace))
::sn/foo
#2021-06-2913:53borkdudethis could be improved though, so issue still welcome#2021-06-2913:53borkdudefor now you could write:
(create-ns 'foo)
(alias 'sn 'foo)
::sn/foo
#2021-06-2913:55nikolavojicicOk, I will post an issue. Thx for workaround.#2021-06-2922:20Joshua SuskaloAre there any common causes for unsupported binding form errors to occur in code generated by hooks?#2021-06-2922:20borkdude@suskeyhose it's usually best to just print the node to see what it looks like#2021-06-2922:21Joshua SuskaloLike right now I'm just putting a symbol into a vector used in an argument list to a fn#2021-06-2922:21Joshua SuskaloYeah, I'm printing the node, and it looks fine
#2021-06-2922:21Joshua Suskalo
<list: (fn [] (fn [field value second item timestamp] [field value second item timestamp] [second field] {:type :http :method :get :body {:field field :value value :timestamp timestam}} ()))>
#2021-06-2922:22Joshua SuskaloThis is what's being generated#2021-06-2922:22Joshua SuskaloAnd it's saying timestamp is an unsupported binding form.#2021-06-2922:22Joshua SuskaloOh, I think I might know#2021-06-2922:22Joshua SuskaloI forgot to turn the symbol into a token node#2021-06-2922:23borkduderight, that's a common thing#2021-06-2922:23Joshua Suskaloyup, that was it#2021-07-0109:09Juλian (he/him)how can I make clj-kondo aware of Quil's defsketch macro? it always flags the following symbol as "unresolved symbol" error#2021-07-0109:11borkdude@julian608 depending on what the macro does, you can use :lint-as. e.g. {:lint-as {foo.bar/defsketch clojure.core/def}}#2021-07-0109:12borkdudesome examples would help (the docs only give docs but no examples)#2021-07-0109:12borkdudeI see:
(defsketch my-sketch
  :size [500 500]
  :draw draw))
#2021-07-0109:13borkdudeI think for this one you'll probably want to use clj-kondo.lint-as/def-catch-all#2021-07-0109:17Juλian (he/him)thanks! linting as def turns it into info "unused public var", and def-catch-all makes it accepted... will try it like that#2021-07-0114:40borkdudeCan clj-kondo also fix the things it reports? No, it only analyzes and reports, but clojure-lsp can use that data to fix :)#2021-07-0407:24ikitommihi. there is an off-by-1 error either on Idea or on clj-kondo on reporting unused function argument location. see f in the pic. greyed out are from cursive, underlines from clj-kondo :thinking_face:#2021-07-0407:25borkdudeCan you paste the code? I can try in emacs#2021-07-0407:27ikitommi
(defn kikka [x y z] (+ y z))
#2021-07-0407:27ikitommi#2021-07-0407:29borkdude#2021-07-0407:30borkdudeCan you disable clj-kondo, to see if it's related?#2021-07-0407:32ikitommidisabling clj-kondo makes the underlining go away, as expected#2021-07-0407:32ikitommi➜ ~ clj-kondo -v clj-kondo v2021.06.01#2021-07-0407:34borkdudeThis is weird, might be an issue with the thing you’re using to integrate clj-kondo, what is that?#2021-07-0407:34ikitommifile-watcher#2021-07-0407:34borkdudeBe back in an hour or so#2021-07-0407:35borkdudeTry the LSP thing, might work better #2021-07-0407:35borkdudeSee docs #2021-07-0407:35ikitommi👍#2021-07-0407:51ikitommiit works. will start using that.#2021-07-0407:54ikitommiok, but, the existing cursive greying out doesnt work with LSP.#2021-07-0407:54ikitommi#2021-07-0407:58ikitommidefault cursive:#2021-07-0409:20borkdudeok, I think the problem is not so much in clj-kondo but in the integration then#2021-07-0409:20borkdudenot sure if there's anything I can do#2021-07-0409:20borkdudeperhaps ask in #cursive#2021-07-0409:23borkdudeI have posted a similar issue about this before I see: https://intellij-support.jetbrains.com/hc/en-us/community/posts/360003434480-File-watcher-inspection-doesn-t-use-line-and-column-correctly#2021-07-0420:29ikitomminote on the LSP-version performance. for large/complex files, it’s really slow on IDEA. Trying to write (inc "kikka") into the end of malli.core ns, takes 10sec just to echo the characters into screen.#2021-07-0420:30ikitommifile-watcher does this only on save, so handles it much better.#2021-07-0420:31ikitommido you have any ideas on how to make the LSP-version work better?#2021-07-0420:31borkdudeI think it can be improved by borrowing some ideas from clojure-lsp, especially the implementation of incremental diffing. or you might want to try clojure-lsp altogether in Cursive, it uses clj-kondo so you would get that for free as well.#2021-07-0420:32borkdudeactually I wrote part of that diffing code in clojure-lsp ;) (not sure if that code is still used)#2021-07-0420:32borkdude@UKFSJSM38 might have some ideas here#2021-07-0420:33borkdudeThe code is here: https://github.com/clj-kondo/clj-kondo.lsp PRs are welcome#2021-07-0420:34ikitommithanks. I would assume the LSP is on different thread and would not block the basic editor features. At least with clj-kondo, seeing result later is totally ok (different case with auto-complete etc)#2021-07-0420:34borkdudetrue. clojure-lsp might already have that and it could be ported#2021-07-0420:36ericdalloI'd suggest test clojure-lsp on intellij and confirm if that issue happens#2021-07-0420:44borkdudeit's kind of worrying that the lsp plugin for intellij is "on hold" since a year ago#2021-07-0420:46ericdalloYeah... @U04V15CAJ the grey feature is a thing on the LS server, the server can add a tag on the diagnostic telling that is unused, then the LS client grey the variable#2021-07-0420:47ericdallohttps://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/feature/diagnostics.clj#L32#2021-07-0420:47ericdalloIn case you want to add that to clj-kondo.lsp#2021-07-0420:48borkdudesure, PR welcome! I don't use the LSP plugin myself but I'm open to improvements for who do#2021-07-0420:48ikitommihmm.. says classpath lookup failed in clojure-lsp. tried to add brew-installed clojure-lsp as the server.#2021-07-0420:49ericdalloAre you using the clojure-lsp official brew one?#2021-07-0420:49ericdallohttps://clojure-lsp.github.io/clojure-lsp/installation/#2021-07-0420:50ikitommi
➜ clojure-lsp --version
clojure-lsp 2021.07.01-19.49.02
clj-kondo 2021.06.18
#2021-07-0420:51ericdalloAlright, check the clojure-lsp log file, you can set it with :log-path setting on .lsp/config.edn#2021-07-0420:53ikitommidon’t have that folder, will create#2021-07-0420:55ericdalloThe lookup is directly related with clojure-lsp running lein classpath or clojure -Spath#2021-07-0420:55ericdalloAnd the same for boot and shadow-cljs projects#2021-07-0420:56ikitommi
2021-07-04T20:54:19.454Z UnknownHost INFO [clojure-lsp.crawler:236] - Automatically resolved source-paths from deps.edn: #{"src" "resources" "test"}
2021-07-04T20:54:19.971Z UnknownHost WARN [clojure-lsp.db:55] - Could not load db [SQLITE_ERROR] SQL error or missing database (no such table: project)
2021-07-04T20:54:19.972Z UnknownHost INFO [clojure-lsp.crawler:27] - Finding classpath via ` clojure -A:dev -Spath `
2021-07-04T20:54:19.979Z UnknownHost ERROR [clojure-lsp.crawler:38] - Error while looking up classpath info in /Users/tommi/projects/metosin/malli Cannot run program "clojure" (in directory "/Users/tommi/projects/metosin/malli"): error=2, No such file or directory
#2021-07-0420:56ikitommiI do have clojure available :thinking_face:#2021-07-0420:56ericdalloYou need clojure installed#2021-07-0420:57ericdalloHum for some reason it's not finding on your PATH or something#2021-07-0420:57ericdalloNever saw this kind of error#2021-07-0421:04ikitommi#2021-07-0421:04ikitomminot sure how can I pass any PATH to LSP, copied clojure executable to the directory, still doesn’t see that.#2021-07-0421:05ericdalloYeah, that seems that won't help, could you try the non Graalvm binary?#2021-07-0421:05ericdalloIts available on GitHub releases page#2021-07-0421:05ericdalloAs clojure-lsp#2021-07-0421:09ikitommisure, didn’t start in 10sec, need to set the timeout.#2021-07-0421:10ericdalloYeah, it'll take 5-10s to start I think#2021-07-0421:10ikitommisame thing.#2021-07-0421:11ericdalloSo it's not a issue with clojure-lsp, probably something with your OS not finding Clojure command#2021-07-0421:11ericdalloI never saw anyone complaining about this error :/#2021-07-0421:12ericdalloWhat OS are you using?#2021-07-0421:13ikitommimacOS 11.4#2021-07-0421:13ikitommipasted the error here: https://gist.github.com/ikitommi/f2cacfe5c389c4459a89f397342293c3#2021-07-0421:14ericdalloThis is how clojure-lsp call that command: https://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/crawler.clj#L32#2021-07-0421:14ericdalloIt's a clojure.java.shell/sh#2021-07-0421:16ericdalloFeel free to open an issue, I'm out of suggestions ATM#2021-07-0421:16borkdudebtw 10 seconds linting is quite extreme, most files take just a few milliseconds#2021-07-0421:17ikitommiit was the non-graalvm-thing, slow startup.#2021-07-0421:17ikitommiI’ll write an issue, thanks both!#2021-07-0421:18borkdude@U055NJ5CC sure, but the startup should happen only once#2021-07-0421:18borkdudeper project#2021-07-0421:18ericdalloNot if the classpath scan didn't work @U04V15CAJ#2021-07-0421:19ericdalloThen clojure-lsp doesn't cache the analysis#2021-07-0421:19borkdudeI mean for clj-kondo.lsp#2021-07-0421:19ericdalloOh, ok#2021-07-0421:19borkdudeclj-kondo.lsp doesn't use a classpath scan, unless you do that yourself from the command line#2021-07-0421:20borkdude(currently, it might be something it could borrow from clojure-lsp in the future)#2021-07-0421:21ericdalloOh, @U055NJ5CC does /`Users/tommi/projects/metosin/malli` is the correct project root?#2021-07-0421:22ericdalloAnd that folder exists?#2021-07-0421:23ikitommiyes, exists#2021-07-0421:24ikitommiand copied clojure there too just for making sure#2021-07-0421:24borkdudeit seems clojure cannot be found? what do you get for which clojure in the shell?#2021-07-0421:25borkdudeintellij/cursive might have an issue with passing through the PATH, I've seen such an issue in #cursive before#2021-07-0421:25borkdudeor perhaps it's in the gtache plugin#2021-07-0421:25ikitommi
➜  ~ which clojure
/usr/local/bin/clojure
➜  ~ clojure
Clojure 1.10.3
user=>
#2021-07-0421:26ericdalloOh, good point, it must be something with Intellij/cursive not using the correct PATH#2021-07-0421:27borkdudeperhaps you could use as the lsp plugin a bb script which spits out the PATH to a file and does nothing else#2021-07-0421:27borkdudeso you can inspect what it gets to see#2021-07-0421:32ericdallo@U055NJ5CC I can try to setup Intellij later, what plugins for intellij are you using to setup clojure-lsp?#2021-07-0421:34borkdudeprobably the gtache lsp plugin as documented in the clj-kondo docs#2021-07-0421:41ikitommiyes, this: https://github.com/gtache/intellij-lsp#2021-07-0421:41ikitommi🙇 *2#2021-07-0421:42ericdalloAlmost sure it's a bug in that plugin, not configuring the PATH correctly#2021-07-0421:44borkdudewell, IntelliJ is a UI program which might not use the same PATH as bash or whatever?#2021-07-0421:44borkdudeat least it could find java in the clj-kondo.lsp plugin#2021-07-0422:21ericdalloYeah, maybe try to start Intellij from a terminal which has clojure on it#2021-07-0507:49ikitommitested from command line, the PATH is corrrect, but still doesn’t work, timeouts after 30sec:
2021-07-05T07:46:22.505Z UnknownHost INFO [clojure-lsp.crawler:27] - Finding classpath via ` clojure -Spath `
2021-07-05T07:46:22.566Z UnknownHost INFO [clojure-lsp.crawler:27] - Finding classpath via ` npx shadow-cljs classpath `
2021-07-05T07:46:51.574Z UnknownHost INFO [clojure-lsp.crawler:204] - Analyzing classpath for project root /Users/tommi/projects/metosin/malli
2021-07-05T07:46:51.575Z UnknownHost INFO [clojure-lsp.crawler:88] - Analyzing 15 paths with clj-kondo with batch size of 1 ...
#2021-07-0507:50ikitommiIDEA logs this:
2021-07-05 10:47:52,122 [ 106969]   WARN - pper.LanguageServerWrapperImpl - Capabilities are null for rawCommand : /usr/local/bin/clojure-lsp
2021-07-05 10:47:52,123 [ 106970]   WARN - ub.gtache.lsp.utils.FileUtils$ - invalid url: ///Users/tommi/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar!/clojure/core.clj (java.net.MalformedURLException: no protocol: ///Users/tommi/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar)
java.net.MalformedURLException: invalid url: ///Users/tommi/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar!/clojure/core.clj (java.net.MalformedURLException: no protocol: ///Users/tommi/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar)
	at java.base/java.net.URL.<init>(URL.java:679)
	at java.base/java.net.URL.<init>(URL.java:541)
	at java.base/java.net.URL.<init>(URL.java:488)
	at com.github.gtache.lsp.utils.FileUtils$.VFSToURI(FileUtils.scala:101)
	at com.github.gtache.lsp.utils.FileUtils$.editorToURIString(FileUtils.scala:89)
	at com.github.gtache.lsp.client.languageserver.wrapper.LanguageServerWrapperImpl.connect(LanguageServerWrapperImpl.scala:181)
	at com.github.gtache.lsp.client.languageserver.wrapper.LanguageServerWrapperImpl.$anonfun$restart$1(LanguageServerWrapperImpl.scala:405)
	at com.github.gtache.lsp.client.languageserver.wrapper.LanguageServerWrapperImpl.$anonfun$restart$1$adapted(LanguageServerWrapperImpl.scala:405)
	at scala.collection.IndexedSeqOptimized.foreach(IndexedSeqOptimized.scala:32)
	at scala.collection.IndexedSeqOptimized.foreach$(IndexedSeqOptimized.scala:29)
	at scala.collection.mutable.WrappedArray.foreach(WrappedArray.scala:38)
	at com.github.gtache.lsp.client.languageserver.wrapper.LanguageServerWrapperImpl.restart(LanguageServerWrapper
#2021-07-0507:52ikitommitested from repl, that doesn’t work:
(java.net.URL. "///Users/tommi/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar")
; =throws=> Execution error (MalformedURLException) at java.net.URL/<init> (URL.java:593).
; no protocol: ///Users/tommi/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar
#2021-07-0507:53ikitommi
➜  ~ ls -l ///Users/tommi/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar
-rw-r--r--  1 tommi  staff  3914649 Mar 11 20:47 ///Users/tommi/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar
#2021-07-0507:55ikitommiso: 1. IDEA doesn’t set the PATH correctly 2. clojure -Spath returns URLs that the plugin doesn’t understand (uses java.net.Url.#2021-07-0507:56ikitommi
➜  malli git:(malli.instrument) ✗ clojure -Spath

src:resources:/Users/tommi/.m2/repository/borkdude/dynaload/0.2.2/dynaload-0.2.2.jar:/Users/tommi/.m2/repository/borkdude/edamame/0.0.11/edamame-0.0.11.jar:/Users/tommi/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar:/Users/tommi/.m2/repository/org/clojure/test.check/1.1.0/test.check-1.1.0.jar:/Users/tommi/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar:/Users/tommi/.m2/repository/org/clojure/core.specs.alpha/0.2.56/core.specs.alpha-0.2.56.jar:/Users/tommi/.m2/repository/org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.jar
#2021-07-0512:27ericdallo@U016JRE24NL the 2. seems a issue with clojure-lsp right? For some reason with IDEA it returns wrong urls#2021-07-0512:27ericdalloOr the lsp plugin is sending malformed URLs#2021-07-0512:28ikitommiabove is what clojure -Spath returns. The plugin uses Url to handle those, which can’t#2021-07-0512:29ikitommie.g. the plugin should be changed or the urls should be preprosessed to be compliant what Url accepts.#2021-07-0512:29ericdalloYeah, but probably is not following some convention somewhere in the plugin as all other editors like VSCode, emacs, vim works#2021-07-0512:30ikitommie.g. add file: to the urls#2021-07-0512:30ericdalloI can try to repro that with IDEA + LSP plugin#2021-07-0512:30ikitommi
(java.net.URL. "file:/Users/tommi/.m2/repository/org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.jar")
works ok
#2021-07-0512:31ericdalloBTW try to disable that timeout, that will not work as sometimes (first time) clojure-lsp will take a while to scan the project and other times it will be fast#2021-07-0512:32ikitommiyeah, did that. just that it doesn’t load any files from classpath as it can’t read the urls#2021-07-0512:33ericdalloYes, let me try understand where the issue is, I'll try to repro#2021-07-0513:32ericdalloI managed to make it work without any errors#2021-07-0513:33ericdalloBut I need to say this LSP plugin is missing a lot of features and its UX is not great IMO 😞#2021-07-0513:33ericdalloI'd suggest you try Calva for VSCode or Emacs if you want the better clojure development experience 😕#2021-07-0513:34ericdalloAnyway, I didn't get any URLs errors :thinking_face: (NixOS here)#2021-07-0713:24Karol Wójcik@U055NJ5CC what font/theme are you using btw?#2021-07-0717:24ikitommi@UJ1339K2B Borealis + Ligaturzed Menlo.#2021-07-0712:51mkvlris there a way to make clj-kondo consider the contents of comment forms to identity unused vars?#2021-07-0714:10borkdude@U5H74UNSF By default clj-kondo lints the contents of comment as if it are top level expressions.#2021-07-0714:10borkdudeNot sure what would be your desired behavior vs the current behavior#2021-07-0714:11mkvlroh#2021-07-0714:11mkvlrthat’s what I want#2021-07-0714:12mkvlr@U04V15CAJ ok, fixed by up lsp+kondo upgrade, thanks!#2021-07-0916:59WestSo I’m using a music creation library overtone.live. The examples tend to add it into the namespace with :use or :refer :all. It makes sense to do this since there isn’t likely to be any collisions with clojure.core and it’s the only library I tend to use in overtone projects. I already got clj-kondo to stop linting :use and :refer :all by adding :linters {:refer-all {:exclude [overtone.live]}} to my kondo config.edn. Now it gives me “Unresolved symbol” when I see why all symbols in the namespace are underlined red. What can I do about this?#2021-07-0917:48borkdude@c.westrom What you can do about this is lint the overtone library while also having a .clj-kondo directory#2021-07-0917:49borkdude@c.westrom See https://github.com/clj-kondo/clj-kondo#project-setup#2021-07-0918:27WestI don’t understand. Do you mean clone overtone.live and then run clj-kondo in a separate terminal to lint it? @borkdude#2021-07-0918:28borkdude@c.westrom You are not using overtone.live as a dependency in a clojure project?#2021-07-0918:28WestI am.#2021-07-0918:28borkdudeproject.clj?#2021-07-0918:30WestDeps.edn, everything works fine when I require overtone.live :as ol or something like that. I just don’t want to have to write ol/ before everything.#2021-07-0918:30borkdude@c.westrom ok, then try as documented in the link I gave you:
mkdir -p .clj-kondo
clj-kondo --lint $(clojure -Spath) --dependencies 
#2021-07-0918:30borkdudeand then try again in your editor#2021-07-0918:42Westunfortunately that did not work, I’m suspecting it might be an issue with lsp#2021-07-0918:43borkdudeoh, you're using LSP, you didn't mention that :)#2021-07-0918:43borkdudeIn that case, try removing .lsp/sqlite.db and restart your editor#2021-07-0918:44borkdudeIf that helps, let me know. If that does not help, I'll have another suggestion.#2021-07-0918:46WestStill a sea of red.#2021-07-0918:46borkdudeok, another attempt. Remove .lsp/sqlite.db and remove .clj-kondo/.cache#2021-07-0918:46borkdudeand then restart your editor#2021-07-0918:49borkdudeoh, I think I see the issue with this. overtone uses a custom macro to import its vars... https://github.com/overtone/overtone/blob/master/src/overtone/live.clj so unfortunately the combination of :use + that namespace won't work very well. you might as well disable the unresolved symbol linter in this namespace :/#2021-07-0918:51ericdalloovertone could have a hook for its macros right? then it would work for clj-kondo if user configure to use the hook, right?#2021-07-0918:51borkdudethat's correct, but the macro doesn't give very much to go by. it's basically "copy that namespace to here"#2021-07-0918:51borkdudehttps://github.com/overtone/overtone/blob/02f8cdd2817bf810ff390b6f91d3e84d61afcc85/src/overtone/live.clj#L4#2021-07-0918:52ericdalloyeah, it's hard to make it work for every corner case indeed 😅#2021-07-0918:53borkdudewell, what you could do is write a hook for this macro and just hard-code the var defs#2021-07-0918:53WestOh, so it’s an overtone thing. I even tried intellij to see if it was just emacs jank causing the issue.#2021-07-0918:54ericdallojust curious, what happens with intellij/cursive? does it works?#2021-07-0918:54borkdudeif cursive uses only static analysis, I expect it to be have similarly#2021-07-0918:55WestFor all the symbols that were red before, I get x cannot be resolved.#2021-07-0918:55borkdudeyou could write a hook which generates
(declare osc chance ...)
from the macro call. All the vars are here: https://github.com/overtone/overtone/blob/02f8cdd2817bf810ff390b6f91d3e84d61afcc85/src/overtone/api.clj#L53
#2021-07-0918:56WestI could look into hooks I guess#2021-07-0918:56borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-07-0918:57borkdudeso you would write a hook that expands a call to
(overtone.api/immigrate-overtone-api)
into
(declare osc chance ...)
, then you re-initialize lsp by throwing away .lsp/sqlite.db and .clj-kondo/.cache + editor restart
#2021-07-0918:57borkdudeand then it should work 😅#2021-07-0918:58borkdudeyou're welcome to PR the hook to overtone itself#2021-07-0918:58borkdudeor to the clj-kondo/config project on github#2021-07-0918:59ericdalloThis is a hook example that maybe can help you: https://github.com/nubank/state-flow/blob/master/resources/clj-kondo.exports/nubank/state-flow/nubank/state_flow.clj#2021-07-0919:03Westthanks guys#2021-07-1116:04ericdalloI'm considering integrate clojure-lsp API with https://github.com/reviewdog/reviewdog, does clj-kondo integrates with it already? I think I saw clj-kondo lint on Github PR lines, was that the integration with review-dog or something else?#2021-07-1116:10borkdude@ericdallo I've heard of it, but I haven't used it.#2021-07-1413:24donavanI have a project that I’m trying to export a config for but it’s a dev time dependency and as such is in an alias. When I run clj-kondo --copy-configs --dependencies --lint "$(clojure -Spath)" it doesn’t import the configs. Only if I place the dependency in the main dependency list does it import. Is there a way to choose aliases to find imports in?#2021-07-1413:41donavanI’ve worked around this by piggybacking on https://github.com/clj-kondo/config/blob/master/src/clj_kondo/config.clj#L21#2021-07-1414:09Joshua SuskaloThere is not a way to get alias information from a dependency at the moment.#2021-07-1414:40donavanYou mean an extra dependency in an alias? If so yeah, that’s what I hit. But have hacked around it by using the clj-kondo/config project and it works (for how long who can say 😄 )#2021-07-1415:22Joshua SuskaloWell if you just wanted to get the path with an alias attached you could just run this:
clj-kondo --copy-configs --dependencies --lint "$(clojure -A:some-alias:other-alias -Spath)"
#2021-07-1415:23Joshua SuskaloI was assuming you wanted an alias from inside one of your dependencies.#2021-07-1415:28donavanfacepalm that is so obvious now that you point it out! Thanks 😄#2021-07-1510:02wdullaerwe have a habit of using macros to generate def's in our libraries#2021-07-1510:02wdullaerrecently clj-kondo started reporting all of these as unresolved-vars#2021-07-1510:03wdullaeraccording to this https://github.com/clj-kondo/config/tree/master/hugsql clj-kondo should accept them if you import them from another namespace, but that seems to no longer be true#2021-07-1510:03borkdudeyou can solve this either with :lint-as {your.cool/macro clojure.core/def} or just disabling that linter. the point of that linter is when you use vars from another namespace that don't exist, you will get a warning.#2021-07-1510:04borkdudethat's only true if there are no other vars in that namespace#2021-07-1510:04borkdudeyou can also :exclude some namespaces in the linter config#2021-07-1510:04borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-var#2021-07-1510:05wdullaerI'm not entirely sure about the empty namespace: it's complaining about unresolved-vars from a namespace that contains just an s/fdef and the macro that generates all these vars#2021-07-1510:06wdullaerI know I can tell clj-kondo to ignore them, but it's a very common pattern in our codebase, and so keeping the ignore list up to date will be a lot of work#2021-07-1510:06borkdudecan you show me an example of such a macro?#2021-07-1510:06wdullaersure#2021-07-1510:08wdullaerI've sent a gist in a dm#2021-07-1514:06wdullaerif someone else reads these messages: I've sorted out the problem using a hook that replaces the macro calls with declare/def statements#2021-07-1514:07wdullaersince these calls are in libraries in my case I also had to reindex the cache with clj-kondo --lint "$(lein classpath)"#2021-07-1514:07borkdudeyep, that's the way to do it, cool that you made it work#2021-07-1520:50seancorfieldJust wanted to mention that this is flagged as "missing :mvn/version, :git/url, or :local/root" although it is legal now in the latest t.d.a:
io.github.cognitect-labs/test-runner {:git/tag "v0.3.1" :git/sha "705ad25"}
#2021-07-1520:57borkdudeah is it. then it shall be updated in kondo.#2021-07-1520:58borkdudewhat is the rule here, if there is a git/sha, what rule should the library symbol have in order for it to be resolved to github/gitlab etc?#2021-07-1520:59Joshua Suskaloit has to conform to ^(com|io)\.(github|gitlab)\..*$ at the moment I think#2021-07-1521:00seancorfield☝️:skin-tone-2: Yup, sounds right. And if it's that format, :git/url can be omitted and the you should have :git/tag AND :git/sha.#2021-07-1521:01Joshua Suskaloneed to check the actual tools deps code though, the guide on http://clojure.org only mentions github, not gitlab#2021-07-1521:01borkdudeif you only have git/tag will the tool then insert the SHA or...? tags can be a bit volatile#2021-07-1521:02seancorfield(I think there's also some wiggle room in t.d.a right now because I put {:tag ".." :sha ".."} in one deps.edn file and it was perfectly happy with it, to my surprise)#2021-07-1521:02Joshua SuskaloIf you have a tag you can have a prefix sha, but if you have no tag you need a full sha#2021-07-1521:02seancorfieldHaving only :git/tag is not allowed I think.#2021-07-1521:02Joshua Suskalobut you always need a :git/sha key.#2021-07-1521:02borkdudegit/tag is more or less for humans, let's say?#2021-07-1521:02Joshua SuskaloYeah, the only exception to needing the :git/sha with the tag is when installing a tool with -Ttools#2021-07-1521:02seancorfield(or just :sha in the old format)#2021-07-1521:03borkdudeis :sha still accepted?#2021-07-1521:03seancorfieldYes.#2021-07-1521:03borkdudeI will copy paste this into an issue#2021-07-1521:04borkdude(https://github.com/clj-kondo/clj-kondo/issues/1318)#2021-07-1521:04borkdudefor now you can use #_:clj-kondo/ignore to ignore false positives#2021-07-1521:05Joshua SuskaloLike I said somewhere else, I think I want to write a tool for use with -T which allows you to specify only a tag and then it'd use rewrite-clj to add the dep to your deps.edn file with a prefix sha.#2021-07-1521:05borkdudeyeah, that's pretty easy. can just be a small bb script even#2021-07-1521:05seancorfieldDeducing URLs from lib names: https://github.com/clojure/tools.deps.alpha/blob/master/src/main/clojure/clojure/tools/deps/alpha/extensions/git.clj#L17-L21#2021-07-1521:06Joshua SuskaloYeah, a bb script would be a good way to package it to run elsewhere, but that is kinda what -T is for on this. Would probably just make it compatible with bb so that it could be run that way if a user wants.#2021-07-1521:07borkdudeoh you mean that script could be installed using -T, yeah, that's meta ;)#2021-07-1521:07borkdudeThanks for letting me know.#2021-07-1521:08borkdudeIf anyone wants to work on this, feel free. I have to write a talk this weekend so I probably won't get to it by then :)#2021-07-1521:08Joshua SuskaloI'd volunteer if my weekend weren't already full#2021-07-1521:08borkdudeno worries, it'll be done eventually#2021-07-1521:08seancorfieldLogic around what can be in git coords: https://github.com/clojure/tools.deps.alpha/blob/master/src/main/clojure/clojure/tools/deps/alpha/extensions/git.clj#L56-L76 -- :tag and :sha are supported but :git/tag and :git/sha are "preferred" it seems (and you can't have both the qualified and unqualified versions).#2021-07-1521:10seancorfield(and I doubt this is urgent for anyone b/c very few folks are going to be a) running the very latest t.d.a and b) using the new, shorter git coords 🙂 )#2021-07-1521:10borkdudemakes sense#2021-07-1614:47tvaughanI'm using clojure-lsp for the first time, and I've noticed it triggers something (clj-kondo, I assume) which writes out clj-kondo settings into the current project directory, namely .clj-kondo/com.wsscode/pathom/config.edn and .clj-kondo/com.wsscode/async/config.edn. This happens when I run clojure-lsp clean-ns and .lsp/sqlite.db does not exist. I already have settings for com.wsscode.pathom in .clj-kondo/config.edn. I wonder if this behavior is correct, and which of these duplicate settings takes precedent when running clj-kondo (which I do frequently on its own on the command-line and via emacs and flycheck.el)? Should I remove my settings and check-in those under com.wsscode? Is there a recommended best-practice? Or is this a clojure-lsp problem and better asked in #lsp?#2021-07-1614:48borkdude@tvaughan This happens when you run clj-kondo with :copy-configs true. The copied config isn't actually activated until you hook it into your config.edn explicitly#2021-07-1614:52tvaughanBut I'm not using :copy-configs anywhere#2021-07-1614:52ericdalloclojure-lsp uses it when calling clj-kondo#2021-07-1614:52ericdalloI don't see why you would want to not use that flag#2021-07-1614:54ericdalloSo, clj-kondo/clojure-lsp doesn't change your config.edn#2021-07-1614:54borkdudethe clojure-lsp command line app should probably not use copy-configs, not sure#2021-07-1614:54borkdudeperhaps it should#2021-07-1614:54tvaughanI'm not saying I don't want to. I'm ignorant of this setting. I'm simply confused and looking for clarification on how to handle these duplicate settings#2021-07-1614:55borkdudeyou can just remove the copied configs#2021-07-1614:56ericdalloOh, I got it, it didn't change the .clj-kondo/config.edn but the .clj-kondo/com.wsscode/pathom/config.edn#2021-07-1614:57borkdudeyes#2021-07-1614:57ericdalloyeah, that is expected indeed to make clj-kondo understand pathom macros in your code#2021-07-1614:57tvaughanIf removing the copied configs is the right choice, how do I prevent this from happening for other people on the team?#2021-07-1614:57ericdalloalso, you probably don't want to add that folder to git#2021-07-1614:57borkdudewell, you do if you end up using that config#2021-07-1614:58tvaughanI do want to share .clj-kondo/config.edn#2021-07-1614:58tvaughanAs well as the hooks#2021-07-1614:58ericdalloIMO, you want to version only .clj-kondo/config.edn#2021-07-1614:58borkdudethe clojure-lsp CLI should probably accept some setting for this#2021-07-1614:58borkdude@UKFSJSM38 no, you also want to version hook code#2021-07-1614:58ericdallothe other folder could be updated in future versions of the hook if it changes#2021-07-1614:59borkdudeyou should check that stuff into git so your team mates are using the same hook code#2021-07-1614:59borkdudeand don't have to run this stuff from the command line themselves#2021-07-1614:59borkdudebut it's a choice everyone can make for them selves. I'm in favor of checking it into git#2021-07-1615:00ericdalloyeah, it works too indeed#2021-07-1615:00ericdalloTLDR commit the copied hooks is probably the best solution for your team#2021-07-1615:01tvaughanIn our case it's important that the team shares the same settings and hooks#2021-07-1913:57lreadAh... this might solve a mystery for me, I noticed that during dev of rewrite-clj, I will sometimes see rewrite-clj's configs copied under rewrite-clj's .clj-kondo dir. I'm using Calva these days so it is probably lsp -> clj-kondo with :copy-configs doing this...#2021-07-1614:49borkdudeso it doesn't hurt necessarily, but those configs are coming from the libraries themselves, so they are likely better than what you have figured out on your own :)#2021-07-1614:53tvaughanYes and no. They cover a couple of things I don't have in my settings, but I've also added a hook which is better#2021-07-1614:53borkdudeah nice. perhaps you can contribute the improvements back to the lib?#2021-07-1614:56tvaughanI could although I didn't write the hook. Someone shared it on slack and I played beta tester. Been working well for me since#2021-07-1615:01borkdudeok#2021-07-1615:01borkdudeperhaps it was @UCFG3SDFV?#2021-07-1615:02tvaughanBah, yeah that's correct, but it's for fulcro not pathom :man-facepalming:#2021-07-1615:06Adam Helins(wasn't me, sorry)#2021-07-1615:06tvaughan
(ns hooks.fulcro
  ""
  {:author "Adam Helins"}
  (:require
   [clj-kondo.hooks-api :as hook]))

(defn defmutation
  [{:keys [node]}]
  (let [[_call
         sym
         & arg+] (:children node)
        docstring (first arg+)
        [[param+
          & fn-like+]
         docstring-2] (if (hook/string-node? docstring)
                        [(rest arg+)
                         docstring]
                        [arg+
                         nil])]
    {:node (hook/list-node (concat [(hook/token-node 'defn)
                                    sym]
                                   (when docstring-2
                                     [docstring-2])
                                   [param+
                                    (hook/vector-node (map #(let [[_sym
                                                                   arg+
                                                                   & body] (:children %)]
                                                              (hook/list-node (list* (hook/token-node 'fn)
                                                                                     arg+
                                                                                     body)))
                                                           fn-like+))]))}))
#2021-07-2207:32Adam HelinsOh yeah, sorry it seems I didn't see your OP, I thought it was about something else. How can I help you? I haven't done any Fulcro in a while but at that time it was working quite well, at least I didn't have any obvious issue.#2021-07-2212:15tvaughanLikewise, it’s working well for me too. I think the only issue now is if this hook should be submitted to fulcro or clj-kondo (no clue how this works)#2021-07-2212:15borkdudePreferably to fulcro itself#2021-07-2212:15borkdudeas that's where it will probably get the most attention and care in the future#2021-07-2212:16borkdudeYou can read here how it works: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-07-2212:16borkdudePerhaps @U066U8JQJ can also help you as he has done this before for certain libraries and I think he is involved in fulcro as well...?#2021-07-2212:23tvaughanThanks @borkdude. @UCFG3SDFV I’d be happy to make the submission on your behalf if that’s ok with you. Which license would you like to use?#2021-07-2214:00Adam Helins@tvaughan Perfectly fine, it's not much so feel free to rewrite what you want and use any license, I'll trust your judgement 🙂#2021-07-2214:01Adam HelinsI didn't PR it because I wasn't sure it was good enough beyond my own workflow and then went to work on something else, haven't been involved with Fulcro since then#2021-07-2214:11tvaughan@UCFG3SDFV Sounds good 👍#2021-07-2222:13wilkerlucioI hadn't create any hooks yet, but Pathom 3 and some libs export the kondo config, the main issue I had when I tried to do that was because I forgot to add resources to the source paths, with that correct it's been working fine#2021-07-1614:51ericdallo@borkdude I didn't know clj-kondo was changing the config.edn for those cases#2021-07-1614:51ericdalloIMO this is a good feature though 🙂#2021-07-1614:53borkdudeit is not changing the config.edn#2021-07-1716:10pezIs there a rationale behind that this gives a redefined var warning?
(comment
  (def foo :foo))

(def foo :bar) ; <- redefined var
#2021-07-1716:12borkdudeyou're probably missing one closing paren of the comment here, right?#2021-07-1716:58pezYeah, here, but not there. 😃 (Fixed the typo)#2021-07-1717:35borkdude@pez If you turn those around, you will not get the redefined warning (since that linter is shut off in the comment section)#2021-07-1717:36borkdudethe above example could be improved of course#2021-07-1717:42borkdudefeel free to post an issue#2021-07-1717:49pezI usually have things like these the other way around. But in this file it made sense with this order. I just might file that issue. 😎#2021-07-2018:18arthurwhat linter would complain about warning sush as :
WARNING: Inst already refers to: #'clojure.core/Inst in namespace: 
#2021-07-2020:36tanzoniteblacklike borkdude says, that's a built in warning from the clojure compiler, not from a linter#2021-07-2020:37tanzoniteblackhttps://github.com/clojure/clojure/blob/b1b88dd25373a86e41310a525a21b497799dbbf2/src/jvm/clojure/lang/Namespace.java#L81#2021-07-2018:54borkdudethis is not a linter warning, but probably a compiler warning#2021-07-2109:49martinklepschI vaguely remember that somebody made a namespace/require visualizer using clj-kondo — does anyone have the link to that?#2021-07-2109:51borkdude@martinklepsch There's two: - https://github.com/benedekfazekas/morpheus - https://github.com/SevereOverfl0w/vizns#2021-07-2309:35robert-stuttafordhas anyone got kondo errors showing in their magit git-status buffer (via a pre-commit hook), and have them navigable straight from the git status buffer?#2021-07-2416:03borkdudeInspired by a discussion with @jimka.issy I'm (re-)considering support direct macroexpansion in hooks. The downsize of this convenience is that errors cannot be precisely located so they are attached to the outer call of the macro.#2021-07-2416:06borkdudeAs a "shortcut" we could support this use case directly by introducing {:hooks {:macroexpand {prog/let+ mymacros/let+}}}#2021-07-2416:07borkdudeYou would still have to copy your macros into the .clj-kondo dir and configure this.#2021-07-2521:07borkdudeMade some progress on the above today.
#2021-07-2521:08borkdudeSee https://github.com/clj-kondo/clj-kondo/discussions/1329#discussioncomment-1048032#2021-07-2602:43dorab
$ cat test.clj
(ns test
  (:require [clojure.pprint :as pp]))
(pp/pprint "foo")
(comment
  (require 'clojure.pprint)
  )

$ clj-kondo --lint test.clj 
test.clj:7:13: warning: duplicate require of clojure.pprint
linting took 14ms, errors: 0, warnings: 1
I was a bit surprised by this.
#2021-07-2606:59borkdudeBut it isn’t incorrect :-)#2021-07-2617:11dorabNot sure. IMO, commented code should be unchecked for any semantics unless explicitly asked for. Moreover, if I use ; (require ...) or #_ (require ...) instead then there is no complaint from clj-kondo. So, why for the (comment ...) form? I can understand checking to see whether a (comment ...) or #_ (...) block parses, but no checks other than that.#2021-07-2617:30borkdudeBecause people usually develop in comment forms and it's useful to have linting there.#2021-07-2617:31borkdudeYou can disable linting in commen forms though, if you want.#2021-07-2617:40dorabThanks. I see that now. {:skip-comments true}. I specifically looked before I posted, but missed it.#2021-07-2608:56yonatanelIs clj-kondo intentionally ignoring unused required namespaces that don’t use :as or :refer? This test I’ve added to clj-kondo.unused-namespace-test passes, but shouldn’t it fail?
(deftest unused-namespace-simple
  (testing "Ignore plain require"
    (is (empty?
          (lint! "(ns foo (:require [clojure.core.async]))"))))
  (testing "Don't ignore"
    (is (seq
          (lint! "(ns foo (:require [clojure.core.async :as async]))")))))
#2021-07-2608:57borkdudethis is intentional#2021-07-2608:58borkdudethe reason is that people can use this for requiring namespaces with side effects, e.g. loading multimethods or specs#2021-07-2609:29yonatanelIs there a way to configure this behavior, or maybe just a hint for what I can temporarily change in clj-kondo to enable it for some cleanup I’m doing?#2021-07-2609:29borkdudecurrently there is no config for it#2021-07-2609:30borkdudeI would just grep/rg the source for "Unused namespace"#2021-07-2610:50lassemaattaI assume the extend-type and extend-protocol macros are not included in the "Clj-kondo only expands a selected set of macros from clojure.core and some popular community libraries."?#2021-07-2610:52lassemaattaor rather: does clj-kondo give any promises on how these macros (and their bodies) are linted?#2021-07-2610:52borkdudeif the macro is built into clojure.core then I think clj-kondo should support it#2021-07-2610:53borkdudeand if not, there are ways to configure clj-kondo to support custom macros#2021-07-2610:53borkdudee.g. you can lint it as if it was another macro, or implement an expansion yourself#2021-07-2610:54borkdudeextend-type and extend-protocol should be supported#2021-07-2610:55lassemaatta#2021-07-2610:58borkdude@U0178V2SLAY Feel free to post an issue.#2021-07-2610:58lassemaattaroger, will do#2021-07-2610:59borkdudeI think this case might be handled in the quick and dirty way: avoid false positives, but don't provide all the analysis#2021-07-2610:59borkdudeand it should be improved#2021-07-2611:05lassemaattahttps://github.com/clj-kondo/clj-kondo/issues/1333#2021-07-2611:05lassemaattaI hope that descriptive enough 🙂#2021-07-2611:06borkdudeyep, thanks#2021-07-2703:13zimabluehi, are there any clojure.core specs for the data which clj-kondo produces?#2021-07-2714:57zendevil.ethIs there a way to turn off false warnings that come up due to using macros?#2021-07-2714:57zendevil.ethlike I might have willingly captured a variable name and that’s showing up as unresolved#2021-07-2714:58zendevil.ethor a macro that takes a variable name also shows that as unresolved#2021-07-2714:59borkdude@ps I'm working on a new feature for macroexpansion. Perhaps you're willing to test it out?#2021-07-2714:59zendevil.ethIt would be my immense pleasure!#2021-07-2714:59borkdudeok, you could read around here: https://github.com/clj-kondo/clj-kondo/discussions/1329 and try it out on the JVM first#2021-07-2715:01borkdudeI can write a summary when my current meeting ends#2021-07-2715:01zendevil.ethThank you that would be great#2021-07-2715:02zendevil.ethgreat work with clj-kondo!#2021-07-2716:23Jim Newton@borkdude do we need a macros HOWTO for cli-kondo?#2021-07-2716:33borkdude@jimka.issy We do.#2021-07-2809:59borkdude@ps @jimka.issy @dave et al, I have merged the macroexpand feature to master and wrote some docs in the issue here: https://github.com/clj-kondo/clj-kondo/issues/1327#issue-952124466#2021-07-3113:17daveI just tried it with the latest clojure-lsp, and it works like a charm. Fantastic work! 💯#2021-07-2810:01borkdudeah well, I guess I will just release this and then gather some feedback until the next release#2021-07-2810:28martinklepschclj-kondo produces a duplicate require warning for a babashka script, is that intended?#2021-07-2810:30borkdude@martinklepsch can you post that code here?#2021-07-2810:30borkdudeI can try locally, if you post the code#2021-07-2810:38borkdudeI'm about to release clj-kondo, so be fast @martinklepsch#2021-07-2810:43martinklepschActually I now ran clj-kondo from the CLI and it didn’t complain so I think it’s probably an issue with the action (old version I guess?)#2021-07-2810:43borkdudecould be#2021-07-2810:44martinklepschIt seems to use the clj-kondo docker image though https://github.com/DeLaGuardo/clojure-lint-action/blob/master/Dockerfile#2021-07-2811:14borkdudeJust released a new version of clj-kondo with the new macroexpansion feature; https://clojurians.slack.com/archives/C06MAR553/p1627470400150500#2021-07-2813:37Noah Bogartset up: i have a macro game.macros/req, and i’m using potemkin to import-export it into game.core. It’s anaphoric, so defines a bunch of vars in a let that are available to the code it wraps: (req (+ (:credits corp) 5)) works because corp is defined by req. in my .clj-kondo/config.edn, i have {:linters {:unresolved-symbol {:exclude [(game.macros/req [corp ...])] so as to ignore those symbols. if I use (:require [game.macros :refer [req]]), the linters work correctly. however, if I put in my config.edn {:lint-as {game.core/req game.macros/req}} , and change the require to be (:require [game.core :refer [req]), all of the req calls are flagged as using undefined symbols#2021-07-2813:37Noah Bogartshort version: how do I make :lint-as work? it seems that :lint-as doesn’t check the :linters rules when determining how to lint as another macro#2021-07-2813:58borkdude@nbtheduke Can you post an issue + repro about this?#2021-07-2815:31Noah Bogarti’ll see what I can do about a repro, the project this is happening in is pretty big#2021-07-2815:39borkdudeI think the main issue is that unresolved-symbol doesn't look at lint-as first or so#2021-07-2815:40borkdudebut repro would be nice to have this confirmed.#2021-07-2813:59borkdudeA workaround for now might be to duplicate the unresolved symbol config#2021-07-2815:08vemvI gave a read to https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand I'm curious, is clj-kondo macroexpanding arbitrary macros now? (would be happy about that) Any limitations or nuances?#2021-07-2815:08borkdudeThe limitations and nuances are hopefully documented in that readme#2021-07-2815:09borkdudeIt doesn't directly execute them from source#2021-07-2815:09borkdudebut you can "copy" them over to the config dir and hook them up#2021-07-2815:09borkdudeand then most of the time they should work, or might require some modifications#2021-07-2815:10vemvok that was what I was asking, i.e. is everything macroexpanded or only when integrated with the hook feature#2021-07-2815:10borkdudeyes, only then#2021-07-2815:10vemvwould be out of the question to macroexpand everything? A few of us use clj-kondo in CI, sometimes with vanilla jvm clojure#2021-07-2815:11borkdudeexecuting all macros isn't possible since some of them do things at runtime other than a pure transformation#2021-07-2815:11vemvlet's say opt-in, for those of us willing to make the tradeoff#2021-07-2815:12borkdudewell, even then it might fail in some cases. I think the new feature should get some more exposure first before taking that next step#2021-07-2815:12borkdudeone could also think of some rewrite-clj script that automatically copies some macros to the config#2021-07-2815:13vemvthanks for considering it, let's see how it goes over time#2021-07-2815:14borkdudethe new feature should be considered as an "easy" trade-off to the more reliable :analyze-call feature at the cost of less precise location info in lint warnings#2021-07-2815:14borkdudefor people who don't want to take the time to deal with :analyze-call, or find it daunting#2021-07-2815:15borkdudeI'm sure some people will come up with clever hacks to copy their macros soon ;)#2021-07-2815:20borkdudeI think the ingredients are there to do so with rewrite-clj and rewrite-edn#2021-07-2815:20borkdudeboth can run in bb, so you could have fast scripts that do so too#2021-07-2815:21borkdudeeventually clj-kondo may support it out of the box, but it may also be a little bit of a rabbit hole to have to support it perfectly, so let's see what happens next#2021-07-2821:07Dereksorry borkdude, but the new tools release means :sha is no longer a requirement, https://github.com/clj-kondo/clj-kondo/blob/626978461cbf113c376634cdf034d7262deb429f/test/clj_kondo/deps_edn_test.clj#L27#2021-07-2821:08borkdude@dpassen1 There is an open issue for this#2021-07-2821:09Derekof course there is#2021-07-2821:09borkdudeFeel free to take it on ;)#2021-07-2821:10DerekI just might#2021-07-2821:13borkdudeI think it's a good "first issue" as it's relatively isolated and relatively easy to understand#2021-07-2821:13borkdudeand there are tests, so if you break something, you'll probably notice#2021-07-2822:17Derek🙂#2021-07-2822:53DerekPut up a draft PR#2021-07-2901:28nathanmarztrying to use :analyze-call hooks to implement some custom linting, but am unable to exclude callsites using the #_{:clj-kondo/ignore [:some-linter]} form#2021-07-2901:28nathanmarze.g. I'm trying to error on calls to satisfies? with this code:
(defn satisfies-hook
  [{:keys [node] :as input}]
  (let [m (meta node)]
    (api/reg-finding! {:message "use of satisfies? is not allowed!"
                       :type :rpl-satisfies?
                       :row (:row m)
                       :col (:col m)
                       })
    node))
#2021-07-2901:29nathanmarzbut this code still causes linting to fail:
(defn platform-executable?
  [o]
  #_{:clj-kondo/ignore [:rpl-satisfies?]}
  (satisfies? PlatformExecutable o))
#2021-07-2901:29nathanmarzany suggestions on how to do this?#2021-07-2907:31borkdude@nathanmarz You need to add :rpl-satisfies? into your linter config as well, {:linters {:rpl-satisfies? {:level :error}}}, have you done this?#2021-07-2907:32borkdudeah I see!#2021-07-2907:32borkdudeyou also need to include :end-row and :end-col, else the ignore annotation doesn't know what the span is where the ignore is valid#2021-07-2913:45borkdude@nathanmarz let me know if that fixes it for you#2021-07-2913:46borkdudeyou could perhaps just assoc onto the metadata and pass that to reg-finding!#2021-07-2914:23borkdudeoh, about the return value: you don't have to return anything, if you're not transforming. just return nil will do#2021-07-2914:27nathanmarz@borkdude that fixed it#2021-07-2914:28nathanmarzreally cool tool, excited to make use of it#2021-07-2914:28borkdudethat's always nice to hear :)#2021-07-2914:44nathanmarzare there any known issues with running kondo via lein?#2021-07-2914:44nathanmarzrunning via CLI works great, but the lein runner is unreliable for me#2021-07-2914:44nathanmarzit sometimes has errors like <path>:11:1: error: Attempting to call unbound fn: #'hooks.core/custom-hook#2021-07-2914:45nathanmarzthese are the commands I'm using:#2021-07-2914:45nathanmarz
lein with-profile kondo clj-kondo --lint 'distributed/src/clj:core/src/clj:distributed/test/clj:core/test/clj' --parallel --config-dir .clj-kondo-jenkins --fail-level error

clj-kondo --lint 'distributed/src/clj:core/src/clj:distributed/test/clj:core/test/clj' --parallel --config-dir .clj-kondo-jenkins --fail-level error
#2021-07-2914:46borkdudeand what is in your lein profile?#2021-07-2914:46borkdudeoh I see#2021-07-2914:46nathanmarzprofile is :kondo {:dependencies [[clj-kondo "2021.07.28"]]}#2021-07-2914:47borkdudeis the hooks.core code inside your .clj-kondo-jenkins folder in hook/core.clj ?#2021-07-2914:47nathanmarzand alias "clj-kondo" ["run" "-m" "clj-kondo.main"]#2021-07-2914:48nathanmarzthe hook are in .clj-kondo-jenkins/hooks/core.clj#2021-07-2914:48borkdudeand you are sure there is a var there named custom-hook?#2021-07-2914:49nathanmarzyes#2021-07-2914:49borkdude(should be, because with the native CLI it works)#2021-07-2914:49nathanmarzalso, the errors with lein are random#2021-07-2914:49nathanmarzsometimes it has those errors, sometimes it doesn't#2021-07-2914:49nathanmarzsometimes it says this: WARNING: error while trying to read hook for...#2021-07-2914:50borkdudecan you try without --parallel?#2021-07-2914:50borkdudeto investigate if this is some kind of concurrency bug#2021-07-2914:53borkdude> WARNING: error while trying to read hook for... can you post the entire message?#2021-07-2914:54nathanmarzit appears to be reliable without --parallel , no errors 6x in a row#2021-07-2914:55nathanmarzalready cleared the CLI, let me try to recreate that error#2021-07-2914:56borkdudehmm, interesting.#2021-07-2914:56borkdudeyeah, I think I know what's going on, the require inside of the interpreter isn't thread safe :)#2021-07-2914:56borkdudecould you please post an issue about this?#2021-07-2914:57borkdudepreferably with a repro, but I think I can reproduce it myself#2021-07-2914:57nathanmarzWARNING: error while trying to read hook for rpl.helpers/returning: Could not resolve symbol: hooks.core/returning-fn#2021-07-2914:57borkdudesatisfies? is a relatively common function, if you lint multiple dirs at the same time, the concurrent require might cause trouble somewhere#2021-07-2914:57borkdudeI should use a locking or so around the loading of the hook code#2021-07-2914:58borkdude@nathanmarz you know what, let me push a quick fix and you can use that deployed artifact in your CI#2021-07-2914:58borkdudejust a minute#2021-07-2914:59nathanmarzthanks#2021-07-2915:03borkdude@nathanmarz try [clj-kondo "2021.07.29-20210729.150232-2"]#2021-07-2915:11borkdudealso made an issue for SCI (https://github.com/borkdude/sci/issues/592)#2021-07-2915:12nathanmarz@borkdude lein with --parallel looks to be reliable now#2021-07-2915:12borkdudeawesome#2021-07-2915:12borkdudeI'll add some tests later#2021-07-2915:13borkdudecurious that this didn't manifest in the binary.#2021-07-2915:40richiardiandreaHi all, I have the following specter path
(def POST-ORDER-VALS
  (sp/recursive-path []
                     p
                     (sp/cond-path map?
                                   (sp/continue-then-stay [sp/MAP-VALS p])
                                   sequential?
                                   (sp/continue-then-stay [sp/ALL p])
                                   set?
                                   (sp/continue-then-stay [sp/ALL p])
                                   sp/STAY)))
And clj-kondo rightly says that p is an "unresolved symbol" p can change, it really depends on who implements the path...is there a way to tell :exclude to ignore recursive-path when linting? Here is what I have now in my config - but it does now work...
{:linters
 {:unresolved-symbol
  {:exclude [thrown-with-data? recursive-path]}}}
#2021-07-2915:42borkdude@richiardiandrea you can do {:exclude [(com.rpl.specter/recursive-path)]} to ignore unresolved symbols inside of a call to that function#2021-07-2915:43richiardiandreaoh ok great, I actually tried (recursive-path) but I guess I needed the fully qualified symbol there - let me try#2021-07-2915:44borkdudeyes, fully qualified#2021-07-2915:48richiardiandreaworks like a charm#2021-07-2915:43borkdudeand (com.rpl.specter/recursive-path [p]) to ignore only p#2021-07-2915:44borkdudeit's a co-incidence that @nathanmarz was just here and just after that someone asks a question about specter :)#2021-07-2915:44borkdudeperhaps specter can provide better support by providing some hooks or macroexpansions as part of the library (if that makes sense for the above case, not sure)#2021-07-2915:44richiardiandreayeah lol I have just seen it up there 😉#2021-07-2915:44richiardiandreaThanks both to you and Nathan for these great tools#2021-07-2921:37borkdude#2021-07-3008:52Jim NewtonHi @borkdude, big bravo for your recent work.#2021-07-3008:54Jim Newtonseems to work well.#2021-07-3009:11Jim Newtonone thing that I noticed which works well, but I was expecting to fail is that (do x) warns that the do is redundant. However if a macro expands to something containing a singleton do this warning is thankfully suppressed. Is that an accident or by design?#2021-07-3009:12borkdudeby design#2021-07-3009:12Jim Newtonhow does it know?#2021-07-3009:12borkdudethe generated nodes are marked as "generated" and the redundant do linter doesn't warn if the node was generated#2021-07-3009:13Jim Newtoncool.#2021-07-3009:16Jim Newtonso if the macro does something like
`(foo (do 41) 
and user-code contains a (do 42) does it know to flag (do 42) but not (do 41) ?
#2021-07-3009:17borkdudewith :macroexpand it doesn't but with :analyze-call it does, because you can re-use the incoming node#2021-07-3009:17borkdude:analyze-call is more powerful, :macroexpand is just for "ease"#2021-07-3009:17Jim NewtonI haven't read the HOW-TO yet.#2021-07-3009:18Jim Newtonthis sort of limitation could be worth noting#2021-07-3009:18borkdudeYes, I think we have to emphasize that :macroexpand comes with these trade-offs.#2021-07-3009:18Jim Newtonindeed.#2021-07-3009:19borkdudebut it may be good for people like yourself who are not yet familiar with :analyze-hook and want to get started more quickly#2021-07-3009:19borkdudenote that :macroexpand will still provide linter warnings for the majority of linters#2021-07-3009:19borkdudejust not for some of these "redundant" ones#2021-07-3009:20Jim Newtonyes it seems like a powerful feature, and easy to use.#2021-07-3009:20borkdudeI agree#2021-07-3009:21Jim Newtoncan you give me the link to the HOWTO again please?#2021-07-3009:21borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-07-3009:31Jim NewtonI'd like to add some things to this doc. What should I do?#2021-07-3009:37borkdudeMake a PR#2021-07-3009:37borkdude(pull request)#2021-07-3009:37borkdudeif you're not familiar with this, there are some docs on the internet explaining how this works. e.g.: https://opensource.com/article/19/7/create-pull-request-github#2021-07-3009:53Jim NewtonI have a patch for backtick/template which makes it compatible with clj-kondo Is that something we should include in the clj-kondo repo, or should I try to convince the backtick folks to take it?#2021-07-3009:56borkdudeI think it depends. What is the patch and which problem does it solve?#2021-07-3009:59Jim Newtonit provides a macro expansion for cli-kondo to use. you can't simply copy the default backtick.clj file into the .clj-kondo directory because the interpreter can't underhand direct references to java class names, and a few more issues. I replace (instance? x Boolean) with (boolean? x) and several similar things. These changes theoretically could but sent upstream to the backtick maintainers. However, I had to change one of the throw exception calls in a way which would probably break the code, but doesn't break it as far as clj-kondo is concerned.#2021-07-3010:01Jim Newtonseems backtick was last touched 6 years ago.#2021-07-3010:02borkdudethe boolean? predicate was introduced in clojure 1.9#2021-07-3010:03borkdudemodifying that library in that way would make it incompatible with clojure 1.8 for example, but that's a trade-off for the lib maintainer to make#2021-07-3012:18borkdude@jimka.issy But you could try to provide a "config" with a macro that that library will export#2021-07-3012:18borkdudeSee https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-07-3012:18borkdudeAnd then users of that library will receive the config automatically, e.g. if they use clojure-lsp#2021-07-3012:31Jim Newtoncould that be made invisible to the users of backtick? I.e. somewhere in the backtick download would be a .clj-kondo configuration which the system would implicitly know about? Or would each user need to modify his .clj-kondo directory to include copies of the files, or entries in the deps.edn file?#2021-07-3012:31borkdude@jimka.issy if the library includes the config in its resources under clj-kondo.exports then it works automatically when you lint the classpath#2021-07-3012:31Jim Newtonor would it be something that I (Jim) would provide independent and in parallel to backtick?#2021-07-3012:32borkdudeyou could also do the latter#2021-07-3012:32borkdudein the latter case, you could also contribute it to https://github.com/clj-kondo/config#2021-07-3012:32borkdudeand if users then include that library on their classpath, or install the config for backtick manually it will also work#2021-07-3012:32Jim Newtonah, so if the maintainers of that library are amenable, I could submit a PR to backtick including this configuration?#2021-07-3012:33borkdudeyes#2021-07-3012:34borkdudeyou could also make your own clj-kondo config project and include that on your own classpath#2021-07-3012:34borkdudeif you want to keep it completely private#2021-07-3012:34borkdudebut it's better if people improved one single config over time, probably in the repo of the original library#2021-07-3012:42Jim Newtonagain, would I hard code a particular sha1 into the deps.edn file of that library? wouldn't that conflict with the sha found elsewhere?#2021-07-3012:43borkdudewhat do you mean by that library in this context?#2021-07-3012:44Jim Newtonaccording to https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration I need to create a deps.edn file at the top level directory of the backtick library with the following content:
{:deps {clj-kondo/config {:git/url ""
                          :sha "e2e156c53c6c228fee7242629b41013f3e55051d"}}}
right?
#2021-07-3012:44borkdudeno#2021-07-3012:44Jim Newtonahhhh. good thing I asked.#2021-07-3012:44borkdudethis is when you would include the clj-kondo/config library which would then contain the config for the backtick library#2021-07-3012:45borkdudebut if you would contribute the config to the backtick library itself, you wouldn't need the clj-kondo/config library#2021-07-3012:46borkdudethe config is extracted from whatever dependency provides it#2021-07-3012:46borkdudeit could be your own custom dependency#2021-07-3012:46borkdudeit doesn't matter#2021-07-3012:46borkdudeas long as the path starts with clj-kondo.exports inside your dependency#2021-07-3012:46borkdude(a better path would maybe have been META-INF/clj-kondo.exports but oh well)#2021-07-3012:48borkdudeduring the linting of dependencies, clj-kondo checks for this and then copies these files into your local config dir#2021-07-3012:48borkdude(if you call clj-kondo with --copy-configs, which clojure-lsp does automatically)#2021-07-3012:48borkdudeso clj-kondo --copy-configs --lint $(clojure -Spath) should copy configs from all dependencies that provide them#2021-07-3012:49Jim Newtonahhh. and I need config.edn inside clj-kondo.exports which contains
{:hooks {
         ;; {:macroexpand {app.bar/baz hook.bar/baz}}}
         :macroexpand {backtick/template     backtick/template}}}
#2021-07-3012:50borkdudeindeed#2021-07-3012:50Jim Newtonalong with the backtick.clj file which contains the (defmacro ...)#2021-07-3012:50borkdudeindeed#2021-07-3012:50borkdudeinside clj-kondo.exports you will need to create a uniquely named dir as well#2021-07-3012:50Jim Newtonsimple, but I'm not sure how I can test it before submitting the PR#2021-07-3012:50borkdudeclj-kondo.exports/backtick/backtick/config.edn#2021-07-3012:51borkdude(the first backtick is an org name, the second the lib name)#2021-07-3012:52borkdude@jimka.issy You can test this by making a local project using :local/root#2021-07-3012:52borkdudeand then doing what you described in that directory#2021-07-3012:52borkdudedeps.edn:
{:deps {backtick/backtick {:local/root "/Users/jim/dev/backtick"}}}
#2021-07-3012:54borkdude(EDITED the above example)#2021-07-3012:55borkdudeand then calling clj-kondo --copy-configs --lint $(clojure -Spath) should dump the config from /Users/jim/dev/backtick/resources/clj-kondo.exports/backtick/backtick into your local .clj-kondo dir#2021-07-3012:55borkdudeNote that the backtick library should add a resources directory to accomodate this config#2021-07-3012:57borkdudealso you will need to add a deps.edn with :paths ["src" "resources"] in backtick or produce a pom.xml from the lein project with lein pom to make :local/root understand it#2021-07-3013:00borkdude(it's quite the ceremony)#2021-07-3013:04Jim Newtonbash-3.2$ clojure -Spath Error building classpath. Manifest type not detected when finding deps for backtick/backtick in coordinate #:local{:root "/Users/jnewton/Repos/backtick"} bash-3.2$#2021-07-3013:05borkdudehttps://clojurians.slack.com/archives/CHY97NXE2/p1627649831039600#2021-07-3013:06Jim Newtonafter added deps.edn to backtick, I have the following:
bash-3.2$ clojure -Spath
src:/Users/jnewton/Repos/backtick/src:/Users/jnewton/Repos/backtick/resources:/Users/jnewton/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar:/Users/jnewton/.m2/repository/org/clojure/core.specs.alpha/0.2.56/core.specs.alpha-0.2.56.jar:/Users/jnewton/.m2/repository/org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.jar
#2021-07-3013:07borkdudelooks good#2021-07-3013:10Jim Newtonwhat do you mean by: Note that the backtick library should add a `resources` directory to accomodate this config#2021-07-3013:10Jim Newtondo I need to create a resources directory in backtick ?#2021-07-3013:10borkdudeyou should put the config inside the resources dir yes#2021-07-3013:10borkdude/Users/jim/dev/backtick/resources/clj-kondo.exports/backtick/backtick/config.edn#2021-07-3013:11borkdudeMake it look like that#2021-07-3013:13Jim NewtonI see the following unexpected but understandable message: Imported config to .clj-kondo/backtick/backtick. To activate, add "backtick/backtick" to :config-paths in .clj-kondo/config.edn.#2021-07-3013:14borkdudeyes, that is expected. In your local config.edn you should then have :config-dirs ["backtick/backtick"]#2021-07-3013:14borkdudeto activate it#2021-07-3013:14Jim NewtonHere is my current config.edn
{:hooks {
         ;; {:macroexpand {app.bar/baz hook.bar/baz}}}
         :macroexpand {clojure-rte.util/print-vals     clojure-rte.util/print-vals,
                       clojure-rte.util/defn-memoized  clojure-rte.util/defn-memoized,
                       clojure-rte.util/defmethod-memoized  clojure-rte.util/defmethod-memoized,
                       clojure-rte.util/exists  clojure-rte.util/exists,
                       clojure-rte.util/setof  clojure-rte.util/setof,
                       clojure-rte.util/forall  clojure-rte.util/forall,
                       clojure-rte.util/forall-pairs  clojure-rte.util/forall-pairs,
                       clojure-rte.util/exists-pair  clojure-rte.util/exists-pair,
                       clojure-rte.util/casep clojure-rte.util/casep,
                       clojure-rte.cl-compat/cl-cond clojure-rte.cl-compat/cl-cond,
                       clojure-rte.cl-compat/with-escape clojure-rte.cl-compat/with-escape
                       clojure-rte.rte-case/rte-case clojure-rte.rte-case/rte-case
                       clojure-rte.rte-case/destructuring-case clojure-rte.rte-case/destructuring-case
                       clojure-rte.rte-case/destructuring-fn clojure-rte.rte-case/destructuring-fn
                       clojure-rte.rte-case/-destructuring-fn-many clojure-rte.rte-case/-destructuring-fn-many
                       clojure-rte.rte-case/dsfn clojure-rte.rte-case/dsfn
                       clojure-rte.rte-case/dscase clojure-rte.rte-case/dscase
                       clojure-rte.typecase/typecase clojure-rte.typecase/typecase
                       ;; backtick/template backtick/template
                       }}}
what do I need to add where?
#2021-07-3013:15Jim Newtonadded :config-dirs parallel with :hooks ?#2021-07-3013:15borkdudeyes, top-level#2021-07-3013:17Jim Newtonhmmm here is my config.edn now
{:config-dirs ["backtick/backtick"]
 :hooks {
         ;; {:macroexpand {app.bar/baz hook.bar/baz}}}
         :macroexpand {clojure-rte.util/print-vals     clojure-rte.util/print-vals,
                       clojure-rte.util/defn-memoized  clojure-rte.util/defn-memoized,
                       clojure-rte.util/defmethod-memoized  clojure-rte.util/defmethod-memoized,
                       clojure-rte.util/exists  clojure-rte.util/exists,
                       clojure-rte.util/setof  clojure-rte.util/setof,
                       clojure-rte.util/forall  clojure-rte.util/forall,
                       clojure-rte.util/forall-pairs  clojure-rte.util/forall-pairs,
                       clojure-rte.util/exists-pair  clojure-rte.util/exists-pair,
                       clojure-rte.util/casep clojure-rte.util/casep,
                       clojure-rte.cl-compat/cl-cond clojure-rte.cl-compat/cl-cond,
                       clojure-rte.cl-compat/with-escape clojure-rte.cl-compat/with-escape
                       clojure-rte.rte-case/rte-case clojure-rte.rte-case/rte-case
                       clojure-rte.rte-case/destructuring-case clojure-rte.rte-case/destructuring-case
                       clojure-rte.rte-case/destructuring-fn clojure-rte.rte-case/destructuring-fn
                       clojure-rte.rte-case/-destructuring-fn-many clojure-rte.rte-case/-destructuring-fn-many
                       clojure-rte.rte-case/dsfn clojure-rte.rte-case/dsfn
                       clojure-rte.rte-case/dscase clojure-rte.rte-case/dscase
                       clojure-rte.typecase/typecase clojure-rte.typecase/typecase
                       ;; backtick/template backtick/template
                       }}}
However, when I run
clojure -M:clj-kondo --copy-configs --lint $(clojure -Spath)
I still see the first line of output
Imported config to .clj-kondo/backtick/backtick. To activate, add "backtick/backtick" to :config-paths in .clj-kondo/config.edn.
#2021-07-3013:17Jim Newtonahhhhh config-paths, not config-dirs ..... hold on#2021-07-3013:20Jim Newton
bash-3.2$ clojure -M:clj-kondo --copy-configs --lint $(clojure -Spath)
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:30:1: warning: redefined var #'backtick/*resolve*
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:32:1: warning: redefined var #'backtick/*gensyms*
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:37:1: warning: redefined var #'backtick/resolve
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:48:1: warning: redefined var #'backtick/unquote?
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:53:1: warning: redefined var #'backtick/unquote-splicing?
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:102:1: warning: redefined var #'backtick/quote-fn
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:107:1: warning: redefined var #'backtick/defquote
/U
#2021-07-3013:20Jim Newtonmaybe I need to remove some caches somewhere?#2021-07-3013:22borkdudehmm, I think clj-kondo should actually not lint your hook code#2021-07-3013:23borkdudeI kind of expected this error#2021-07-3013:23Jim Newtonremoving .cache and .cpcache seems to have no effect.#2021-07-3013:23borkdudeit should consider namespaces from hook code and application code differently#2021-07-3013:23borkdudenow it thinks they are the same ;)#2021-07-3013:24Jim Newton
bash-3.2$ clojure -M:clj-kondo --copy-configs --lint src
src/clojure_rte/genus.clj:35:31: warning: Unresolved var: template
src/clojure_rte/genus_spec.clj:27:31: warning: Unresolved var: template
src/clojure_rte/rte_case.clj:29:31: warning: Unresolved var: template
src/clojure_rte/rte_construct.clj:37:31: warning: Unresolved var: template
src/clojure_rte/rte_construct.clj:2113:34: warning: unused binding sink-state-id
src/clojure_rte/rte_extract.clj:32:9: warning: unused binding canonicalize-pattern
src/clojure_rte/typecase.clj:25:31: warning: Unresolved var: template
src/clojure_rte/xymbolyco.clj:34:31: warning: Unresolved var: template
linting took 1742ms, errors: 0, warnings: 8
#2021-07-3013:24borkdudeyes, this is the same problem basically. the hook namespace replaces the real namespace. instead, we should just never save the results from linted hook code to the cache#2021-07-3013:24Jim NewtonI wonder if clojure if finding the correct template library now?#2021-07-3013:26borkdudethis warrants another issue on github#2021-07-3013:26borkdudeso far this wasn't a problem since the hook namespaces were always called differently than application code#2021-07-3013:26Jim Newtonsorry, me no understand.#2021-07-3013:27borkdudeok, what happens is that clj-kondo lints the backtick library. but while linting it, it also lints the hook namespace code and mistakes it for the original namespace since it has the same name#2021-07-3013:28borkdudeand then when you use this library from your code, you will see some vars are "unresolved" because they are not in the hook code#2021-07-3013:28borkdudeinstead, clj-kondo should never "replace" the results of linted hook code in the cache#2021-07-3013:29Jim Newtonso what triggered clj-kondo to lint the backtick library?#2021-07-3013:29borkdudeclj-kondo lints your config code as well, that's the problem#2021-07-3013:29Jim Newtonahhh was that the --lint $(clojure -Spath) ?#2021-07-3013:31borkdudeyes, that code is on the classpath. which was the point, because else it wouldn't have been copied#2021-07-3013:32borkdudebut clj-kondo just skip linting it#2021-07-3013:32borkdudelemme push a quick fix for this#2021-07-3013:37borkdude@jimka.issy Can you test commit 07fd7d0ca055e09072d9ea9779e9e5c73e0c0026 of clj-kondo?#2021-07-3013:41Jim Newtonoops was away from desk.#2021-07-3013:42Jim Newton
bash-3.2$ clojure -M:clj-kondo --copy-configs --lint src
Checking out:  at 07fd7d0ca055e09072d9ea9779e9e5c73e0c0026
src/clojure_rte/genus.clj:35:31: warning: Unresolved var: template
src/clojure_rte/genus_spec.clj:27:31: warning: Unresolved var: template
src/clojure_rte/rte_case.clj:29:31: warning: Unresolved var: template
src/clojure_rte/rte_construct.clj:37:31: warning: Unresolved var: template
src/clojure_rte/rte_construct.clj:2113:34: warning: unused binding sink-state-id
src/clojure_rte/rte_extract.clj:32:9: warning: unused binding canonicalize-pattern
src/clojure_rte/typecase.clj:25:31: warning: Unresolved var: template
src/clojure_rte/xymbolyco.clj:34:31: warning: Unresolved var: template
linting took 1758ms, errors: 0, warnings: 8
Do I need something else other than just changing the sha code?
#2021-07-3013:42borkdudeyes, re-lint the classpath#2021-07-3013:44Jim Newton
bash-3.2$ clojure -M:clj-kondo --copy-configs --lint $(clojure -Spath)
/Users/jnewton/Repos/backtick/src/backtick.clj:58:11: error: Unresolved symbol: template
/Users/jnewton/Repos/backtick/src/backtick.clj:101:11: error: Unresolved symbol: syntax-quote
clojure/core.clj:35:17: warning: unused binding &form
clojure/core.clj:35:23: warning: unused binding &env
clojure/core.clj:40:18: warning: unused binding &form
clojure/core.clj:40:24: warning: unused binding &env
clojure/core.clj:45:20: warning: unused binding &env
clojure/core.clj:210:9: warning: Missing else branch.
clojure/core.clj:223:27: warning: unused binding fdecl
clojure/core.clj:294:17: warning: unused binding &form
clojure/core.clj:294:23: warning: unused binding &env
clojure/core.clj:325:23: warning: Missing else branch.
#2021-07-3013:44borkdudeyes, ok#2021-07-3013:44borkdudeand now re-lint your src#2021-07-3013:44borkdude(you don't need config-configs for that anymore)#2021-07-3013:45Jim Newton
bash-3.2$ clojure -M:clj-kondo  --lint src
src/clojure_rte/genus.clj:35:31: warning: Unresolved var: template
src/clojure_rte/genus_spec.clj:27:31: warning: Unresolved var: template
src/clojure_rte/rte_case.clj:29:31: warning: Unresolved var: template
src/clojure_rte/rte_construct.clj:37:31: warning: Unresolved var: template
src/clojure_rte/rte_construct.clj:2113:34: warning: unused binding sink-state-id
src/clojure_rte/rte_extract.clj:32:9: warning: unused binding canonicalize-pattern
src/clojure_rte/typecase.clj:25:31: warning: Unresolved var: template
src/clojure_rte/xymbolyco.clj:34:31: warning: Unresolved var: template
linting took 1690ms, errors: 0, warnings: 8
#2021-07-3013:45borkdudeWhat is inside your :clj-kondo alias?#2021-07-3013:47Jim Newton
{:aliases
 {:clj-kondo
  {:replace-deps
   {clj-kondo/clj-kondo
    {:git/url ""
     
     :sha "07fd7d0ca055e09072d9ea9779e9e5c73e0c0026" ;; "30c878d719c7630ee5f5e51876ba780c5667b23f"
     }}
   :main-opts ["-m" "clj-kondo.main"]}}
 :deps {backtick/backtick {:local/root "/Users/jnewton/Repos/backtick"}}
}
#2021-07-3013:48Jim Newtondid you make a copy of my repo?

I have pushed everything if you'd like to take a look
#2021-07-3013:49borkdudeOh I see what the problem is.#2021-07-3013:49Jim Newtonoops but you don't have my local backtick directory. details 🤪#2021-07-3013:49borkdudeThe template var is defined using a custom macro. https://github.com/brandonbloom/backtick/blob/b927924949a86eb3706dec3f6c224ff79b1de7ae/src/backtick.clj#L58#2021-07-3013:50borkdudeYou can solve that one using :lint-as {backtick/defquote clojure.core/declare} config#2021-07-3013:50Jim Newtonyes indeed.#2021-07-3013:50borkdudeI will revert my previous commit to get this sorted out better and not to confuse things#2021-07-3013:51Jim Newtonbut wait. why is that file being linted anyway?#2021-07-3013:51borkdudeso clj-kondo knows about the arities, types, etc from that library#2021-07-3013:51borkdudeso when you call that library, clj-kondo can provide you with better linting#2021-07-3013:52Jim Newtonoic#2021-07-3013:52borkdudeReverted the commit in 5fd42138312f7a41126c48edb32c79f42b036cbf#2021-07-3013:53Jim Newtonso I need to add :lint-as {backtick/defquote clojure.core/declare} in the file backtick/resources/clj-kondo.exports/backtick/backtick/config.edn ?#2021-07-3013:53borkdudeyes#2021-07-3013:54Jim Newtonand :lint-as is parallel with :macroexpand, or rather parallel with :hooks ?#2021-07-3013:54borkdudetop level#2021-07-3013:57Jim Newtonhmmmm. now
clojure -M:clj-kondo --copy-configs --lint $(clojure -Spath)
gives the following output
#2021-07-3013:58Jim Newton
bash-3.2$ clojure -M:clj-kondo --copy-configs --lint $(clojure -Spath)
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:30:1: warning: redefined var #'backtick/*resolve*
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:32:1: warning: redefined var #'backtick/*gensyms*
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:37:1: warning: redefined var #'backtick/resolve
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:48:1: warning: redefined var #'backtick/unquote?
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:53:1: warning: redefined var #'backtick/unquote-splicing?
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:102:1: warning: redefined var #'backtick/quote-fn
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:107:1: warning: redefined var #'backtick/defquote
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:116:1: warning: redefined var #'backtick/class-symbol
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:119:1: warning: redefined var #'backtick/namespace-name
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:122:1: warning: redefined var #'backtick/var-namespace
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:125:1: warning: redefined var #'backtick/var-name
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:128:1: warning: redefined var #'backtick/var-symbol
/Users/jnewton/Repos/backtick/resources/clj-kondo.exports/backtick/backtick/backtick.clj:131:1: warning: redefined var #'backtick/ns-resolve-sym
clojure/core.clj:35:17: warning: unused binding &form
clojure/core.clj:35:23: warning: unused binding &env
clojure/core.clj:40:18: warning: unused binding &form
clojure/core.clj:40:24: warning: unused binding &env
clojure/core.clj:45:20: warning: unused binding &env
clojure/core.clj:210:9: warning: Missing else branch.
#2021-07-3013:58Jim Newtonis that what you expect?#2021-07-3013:59borkdudeok, let me re-apply my commit from just before ;)#2021-07-3014:00borkdudetry d5e0ec443fecbc01f8fc5aae4de69cce2e1e72be#2021-07-3014:28Jim Newtongot distracted with work.#2021-07-3014:29Jim NewtonOK, here is the output
bash-3.2$ clojure -M:clj-kondo --copy-configs --lint $(clojure -Spath)
Checking out:  at d5e0ec443fecbc01f8fc5aae4de69cce2e1e72be
clojure/core.clj:35:17: warning: unused binding &form
clojure/core.clj:35:23: warning: unused binding &env
clojure/core.clj:40:18: warning: unused binding &form
clojure/core.clj:40:24: warning: unused binding &env
clojure/core.clj:45:20: warning: unused binding &env
clojure/core.clj:210:9: warning: Missing else branch.
clojure/core.clj:223:27: warning: unused binding fdecl
clojure/core.clj:294:17: warning: unused binding &form
clojure/core.clj:294:23: warning: unused binding &env
clojure/core.clj:325:23: warning: Missing else branch.
clojure/core.clj:454:16: warning: unused binding &form
clojure/core.clj:454:22: warning: unused binding &env
clojure/core.clj:544:4: warning: unused binding x
clojure/core.clj:794:5: warning: unused binding x
clojure/core.clj:826:5: warning: unused binding x
clojure/core.clj:908:5: warning: unused binding x
clojure/core.clj:1063:5: warning: unused binding x
clojure/core.clj:1078:5: warning: unused binding x
clojure/core.clj:1093:5: warning: unused binding x
clojure/core.clj:1108:5: warning: unused binding x
clojure/core.clj:1451:14: warning: unused binding args
clojure/core.clj:2307:56: warning: unused binding e
clojure/core.clj:2511:4: warning: unused binding flags-ignored-for-now
clojure/core.clj:2731:1: warning: redefined var #'clojure.core/map
clojure/core.clj:3301:1: warning: redefined var #'clojure.core/dotimes
clojure/core.clj:3651:31: warning: unused binding writer
clojure/core.clj:3654:28: warning: unused binding writer
clojure/core.clj:3937:12: error: Unresolved symbol: setInt
#2021-07-3014:30Jim Newtonperhaps those are real errors from that library?#2021-07-3014:31Jim Newton
bash-3.2$ clojure -M:clj-kondo  --lint src
src/clojure_rte/rte_construct.clj:2113:34: warning: unused binding sink-state-id
src/clojure_rte/rte_extract.clj:32:9: warning: unused binding canonicalize-pattern
linting took 1641ms, errors: 0, warnings: 2
#2021-07-3014:34Jim Newtonindeed, those are two error/issues in my code. I don't yet know how to solve them. I think they indicate something is wrong more than just lint.#2021-07-3014:36borkdudeok cool
#2021-07-3015:39Jim Newtondo you think there are other widely used macros which clj-kondo users might be exploiting, or is template the only one. My gut feel is there are several widely used macros. if clj-kondo knew how to support them it might be easier the convincing maintainers of xyzzy-library to adopt support for clj-kondo which they no nothing about ????#2021-07-3015:39Jim NewtonI'm happy to submit my template support for clj-kondo. Not sure what I need to change.#2021-07-3015:42borkdudeclj-kondo has built-in support for some macros but we can't possible support all of the macros from the ecosystem. for that the library has to be widely used. I don't think backtick is that widely used#2021-07-3015:42borkdudeso for now the config can live in clj-kondo/config#2021-07-3015:56Jim NewtonI don't see such a directory. how do the contents of clj-kondo/config relate the the contents of backtick/resources/clj-kondo.exports ?#2021-07-3015:58borkdudeI mean this repo: https://github.com/clj-kondo/config#2021-07-3014:47Jim Newton@borkdude maybe you'd like to join this discussion, in case I've given some false information. https://github.com/brandonbloom/backtick/issues/8#2021-07-3016:34FiVoWhat is the standard way of developing a hook. I added clj-kondo to my deps. I am getting Could not locate clj_kondo/hooks_api.... when evaluating
(ns hooks.macros
  (:require [clj-kondo.hooks-api :as api]))
#2021-07-3016:35FiVoFollowing the example here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#transformation#2021-07-3016:37borkdude@finn.volkel The hook code runs in an interpreter during linting. You don't actually call it as a library from clojure. You call the API from within the lint config code.#2021-07-3016:38borkdudeTo develop you just call the linter#2021-07-3016:38borkdudewith some examples#2021-07-3016:39FiVoI see thanks#2021-07-3017:08FiVoso I added the following line to my config :hooks {:analyze-call {ramper.util.macros/cond-let hooks.macros/cond-let}} , wrote the hook code and tried with
cat src/clj/ramper/util/macros.clj | clj-kondo --lint -
I am still getting errors. How I do figure out where stuff goes awry? Is my hook code bad if so how do I check that?
#2021-07-3017:29FiVoSorry, maybe not clear from the above. I also have an example of call cond-let in macros.clj.#2021-07-3017:55borkdudeTry adding a println in your cond-let hook code#2021-07-3017:55borkdudeand see if it's properly being triggered#2021-07-3017:55FiVotried that, it doesn't#2021-07-3017:57FiVoalso changed hooks.macros/cond-let to hooks.cond-let/cond-let . I don't know if that is important.#2021-07-3017:57borkdudeit has to correspond to a hooks/cond_let.clj file in your .clj-kondo dir#2021-07-3017:58borkdudein that case#2021-07-3018:00FiVoyes#2021-07-3018:02FiVoalso the with-bound example should change from {:keys [:node]} -> {:keys [node]}#2021-07-3018:02FiVoin the argument list#2021-07-3018:04borkdudenot really#2021-07-3018:04borkdudeboth are valid#2021-07-3018:05borkdudealthough keyword is less common#2021-07-3018:05FiVoare sorry, didn't know that.#2021-07-3018:07FiVoupgraded clj-kondo, getting a warning now#2021-07-3018:57FiVoI got the thing to work from the command line, but in emacs + flycheck I am getting (in case of uneven forms, i.e. it should report an error):
Suspicious state from syntax checker clj-kondo-clj: Flycheck checker clj-kondo-clj returned 3, but its output contained no errors: /home/fv/Code/Clojure/ramper/src/clj/ramper/util/macros.clj::: error: cond-let requires an even number of forms
linting took 23ms, errors: 1, warnings: 0

Try installing a more recent version of clj-kondo-clj, and please open a bug report if the issue persists in the latest release.  Thanks!
How do I fix that? I upgraded my emacs packages. I am off for the day, so not urgent.
#2021-07-3018:57borkdudeah, it's missing location metadata on the node#2021-07-3018:57borkdudeyou need to add that using with-meta#2021-07-3020:33AJ JaroThere’s a reference. to clj-kondo.hooks-api in the https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#custom-lint-warnings. Should that be a reference to a different namespace now?#2021-07-3020:33borkdude@ajarosinski No. This namespace is exposed to hook code which is configured to run using the :hooks config#2021-07-3020:33borkdudeit is not exposed as a library to the JVM for general purpose Clojure programming#2021-07-3020:35AJ Jaro@borkdude Thanks for the quick reply; I see. There’s some notification that when using api/sexpr it can’t be resolved, but maybe that’s a Cursive warning#2021-07-3020:35borkdudegotcha#2021-07-3021:42AJ JaroIt seems like it might be possible to highlight a finding containing multiple nodes on a hook using a row , end-row, col, and end-col. I’m having a bit of trouble doing that. For example, below I’d like to highlight from [:img#pic] through [:#pic-col. Is that possible?
(m/deftemplate
  test-fn
  (resource "") 
  [{:keys [data test-data]}]
  [:img#pic] (if data (m/set :src data) nil)
  [:#pic-col])
#2021-07-3021:48AJ JaroHere’s how I’m attempting to register the finding
(when-not (even? (count body))
      (let [{:keys [row col]} (some-> node :children (nth 4) meta)
            end-metadata (some-> node :children last meta)]
        (api/reg-finding! {:message "Must have an even number of arguments in the body"
                           :type    :m-template
                           :row     row
                           :end-row (:end-row end-metadata)
                           :col     col
                           :end-col (:end-col end-metadata)})))
#2021-07-3021:48AJ JaroIt registers the finding but only on the [:img#pic] node#2021-08-0310:35borkdude#2021-08-0310:38borkdude@ajarosinski Sorry, I didn't see your question#2021-08-0310:40borkdude@ajarosinski I think this will work when you output EDN or text, but not all editors may supports this, so "it depends"#2021-08-0315:12DerekIf I’ve written a kondo ‘hook’ function for a macro in a third-party library, what’s the best way to distribute it? Make a PR against that library? Or does it need to go in https://github.com/clj-kondo/config ?#2021-08-0315:14borkdude@dpassen1 Cool. Which lib?#2021-08-0315:14DerekGary Fredericks’ test.chuck#2021-08-0315:16borkdudeI think the preferred way is to PR it against the lib but if the maintainer of the lib isn't comfortable with this, you can PR it against clj-kondo/config or maintain it yourself somewhere#2021-08-0315:16borkdudeIf you maintain it yourself, you can recommend to users of test.check to also include your lib (with only config) and then it will be automatically copied#2021-08-0315:17borkdudeRead https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration for more#2021-08-0315:17borkdudeI think clj-kondo/config is nice since it's a central place where people might look for a config#2021-08-0315:19DerekThanks. I’ll clean it up and try to get in contact with the author of the lib#2021-08-0320:19hugodWe have a macro that imports a namespace (creates forwarding defs). Does clj-kondo have an api that enables a hook to access the cached symbols from a namespace? which would allow transforming the import into a sequence of defn/def forms.#2021-08-0320:20borkdude@hugod currently not. but you could generate this macro using runtime info and then dump it into the config folder#2021-08-0320:22hugodwhat do you mean by “runtime info”?#2021-08-0320:22borkdudein the REPL#2021-08-0320:22borkdudeor some function you run periodically#2021-08-0320:22hugodoh, completely outside clj-kondo#2021-08-0320:22borkdudeyes. e.g. when you eval the namespace you could trigger a side effects which writes the macro#2021-08-0320:27hugodthat’s a possibility, I guess, though would require changing our codebase to something very specific for each current call site of the import macro. Seems like it would be simpler to just read the transit files generated by clj-kondo, and use it to rewrite the import calls.#2021-08-0320:50borkdude@hugod The transit files are subject to change, not really a public API. The public API for this is https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#2021-08-0320:52hugodright - just looking to see how easy it would be to extend that api. Would that be something you would be open to accepting a patch for?#2021-08-0320:52borkdudedo you mean, the API of the hooks right?#2021-08-0320:52borkdudeor the analysis data?#2021-08-0320:54hugodsorry, misread. Yes extending the hooks api to include a function to get the cached data for a namespace.#2021-08-0320:54borkdudeI think that could be useful. But there is one problem here: the cache may not already been populated.#2021-08-0320:55hugodor it may not be recent. But that seems no different to the behave when linting with a require :all.#2021-08-0320:56borkdudetrue#2021-08-0320:56borkdudealso the namespace may be coming from clj, cljs or cljc (depending on the caller namespace, this is a bit of trickiness that this API should then account for)#2021-08-0320:58borkdudewhat about leveraging the analysis data, which has everything of your project, and use that to generate the macro?#2021-08-0320:58borkdudethere is now also a :custom-lint-fn which is called after analysis with the findings + analysis where you could do this#2021-08-0320:58borkdudeon the JVM#2021-08-0320:59borkdudethat might also not be ideal since you would have to run this function every time you change an imported namespace#2021-08-0321:00borkdudethere are some people who went completely away from these kinds of macros towards a code generation approach#2021-08-0321:00borkdudeclj-kondo has built-in support for this well known macro, I forgot the name#2021-08-0321:01hugodThe import macro is used multiple times on different namespaces, so each instance would have to become unique, iiuc.#2021-08-0321:02borkdudepotemkin was the name#2021-08-0321:02hugodright, unfortunately we’re not using that#2021-08-0321:02hugodwhat’s the code generation approach?#2021-08-0321:03hugodoh - could we use :lint-as and point to the potemkin versions?#2021-08-0321:04borkdudeif @lee is around he could tell you what he did to replace potemkin with code generation. the gist of it is instead of letting the macro generate code at runtime, you generate the code and save that to a file#2021-08-0321:04borkdudeyes, you can use :lint-as iff the syntax is the same#2021-08-0321:05borkdudebut I assume your macro doesn't literally get to see the var symbols?#2021-08-0321:06hugodRight, it’s literal just passed the namespace name. potemkin doesn’t have an equivalent.#2021-08-0321:07hugodI’ll have a think about how generating a macro implementation could work in the build.#2021-08-0321:07borkdudeperhaps it could be part of the macro itself#2021-08-0321:08borkdudesince all those vars go through there anyway#2021-08-0321:08hugodcould be - would require some logic to make it dev time only#2021-08-0321:15borkdudee.g.
(defmacro import-all-vars [ns]
  (let [vars (ns-publics ns)]
         defs (map (fn [v] (list 'def v (symbol (str ns) (str v))) (keys vars)
         _ (spit ".clj-kondo/macros.clj" `(defmacro ~'import-all-vars .... (case ... ns (do 
This is very sketchy pseudocode. I think the clj-kondo config macro would have to be extensible using a multimethod or so, so each time the macro is called with a different ns, this different ns registers another defmethod to which the macro can dispatch and appends that to the file.
#2021-08-0321:16borkdudeyou could also just disable the unresolved var linter for an imported namespace#2021-08-0321:20borkdudeif that doesn't work out, we can see if we can provide the hook API with some cache info#2021-08-0321:22borkdudeI think I've done a similar thing to make :refer :all work better#2021-08-0321:23hugodI’ll take a look at the implementation of refer :all.#2021-08-0321:25borkdudehttps://github.com/clj-kondo/clj-kondo/blob/07e6d6ce824a8a58d8fbb82652177601b29b0f8d/src/clj_kondo/impl/analyzer/namespace.clj#L218#2021-08-0321:25borkdudeI could simplify that case to not take into account cljs, etc. since :refer :all is only supported in clojure (JVM)#2021-08-0321:26borkdudeit's the only spot in clj-kondo where I read from the cache during analysis#2021-08-0321:30borkdudeso to think about an API: (hooks-api/var-names ns-sym) and this would return all the names. if everything was just clojure, then this would be it.#2021-08-0321:30borkdudebut cljs/cljc makes it a little bit more difficult.#2021-08-0321:31borkdudeso perhaps it should take an options map where you can specify more options or so#2021-08-0321:32borkdudeI'll let you think about it a little bit, at least you know where to look now. And I'm going to sleep on it as well :)#2021-08-0321:37hugodThanks for the detailed, useful response, as usual! Have a good evening!#2021-08-0321:37borkdudeis the semantics of your macro that ns1 is basically the same as ns2 ?#2021-08-0321:51hugodNo, the importing namespace adds stuff#2021-08-0321:38littleli@borkdude I spotted the latest clj-kondo don't have a windows release artifact#2021-08-0321:38borkdudehmmm#2021-08-0321:39borkdudefailing test#2021-08-0321:39borkdudethanks for noticing, I'll make a fix#2021-08-0321:41littleli👍#2021-08-0321:52borkdudeI'll probably do a new release tomorrow#2021-08-0321:52borkdudeWindows path stuff#2021-08-0321:53littlelino problem, if you do new artifact is going to be picked up.#2021-08-0321:59borkdude@UKFSJSM38 ^ I'll probably have to do a new release tomorrow for Windows#2021-08-0409:14seriogaDo we have :missing-docsring linter for namespace declarations?#2021-08-0414:07lread@hugod re: potemkin like things. For me, the cost outweighed the benefit for rewrite-clj, and I went with a build time template approach. https://github.com/clj-commons/rewrite-clj/blob/main/doc/design/01-merging-rewrite-clj-and-rewrite-cljs.adoc#potemkin-import-vars, but am happy to answer any further questions you might have.#2021-08-0415:01hugodThanks! I’ll have a read#2021-08-0417:11Joshua SuskaloIs there any way to get a stacktrace of an exception in a hook?#2021-08-0417:12Joshua SuskaloFor example ATM I'm getting a problem where sexpr doesn't work on nil. That's fine, but my hook is long and complicated, and it'd speed debugging if I could get a stacktrace.#2021-08-0517:33ericdallo@borkdude can we expose clj-kondo.core-impl/resolve-config in the public API? 🧵#2021-08-0517:34ericdalloSince clojure-lsp public linters now lives in clj-kondo config, clojure-lsp needs to check that in other features like code lens which check that same config key#2021-08-0517:34ericdalloexposing that would help a lot#2021-08-0517:35ericdallo(Actually I'm using that impl ns ATM)#2021-08-0517:35borkdudeah#2021-08-0517:35borkdudebut the config is already part of run!, isn't this enough?#2021-08-0517:36ericdallobut I don't need that config, I need the one in user project root or in the home one#2021-08-0517:36ericdallolike the final config#2021-08-0517:36borkdudethe "final" config is the one in run!#2021-08-0517:36borkdudeit's the one that clj-kondo really used#2021-08-0517:36ericdallooh, yes, that would partially work, but I'd like to make something that doesn't need to restart the server, like check everytime to see if the config changed#2021-08-0517:37borkdudeso tell me, regardless of the impl function, "I need a function foo that given argument x returns y", then what would this be?#2021-08-0517:38ericdallosomething like (clj-kondo.core/config project-root) which brings the merged edn of home user clj-config + project clj-kondo config#2021-08-0517:39ericdallojust making that impl public would work as I'm doing something like:
(defn kondo-config [db]
  (kondo.core-impl/resolve-config (io/file (:project-root-uri db)) {}))
#2021-08-0517:39borkdudesorry, you have to be more specific. the merged config is already in the output of run! so I don't understand what you're missing yet#2021-08-0517:42ericdalloSorry, let me try to be more specific • user has lsp running in a project • user change clj-kondo/.config of that project or its clj-kondo home dir config changing the :linters clojure-lsp/unusued-public-var setting, adding a exclude or something • next time clojure-lsp process code lens for that file, it will call this new function which would bring the config#2021-08-0517:42ericdallowe could update the db with clj-kondo output of run!#2021-08-0517:42ericdallobut that would need user to edit the file#2021-08-0517:43ericdalloto clojure-lsp run kondo there#2021-08-0517:43borkdudeso you are watching these files?#2021-08-0517:43ericdalloyeah, not really, you are right, the next time code lens need to be calculated kondo would run as well#2021-08-0517:44ericdalloI'll use the output of run! and test if it works 🙂 thanks!#2021-08-0517:59ericdalloIt worked perfectly 🙂#2021-08-0613:59Noah BogartI’m using Specter (https://github.com/redplanetlabs/specter) in my current project and clj-kondo can’t seem to resolve some of the “navigators” (https://github.com/redplanetlabs/specter/wiki/List-of-Navigators):#2021-08-0613:59Noah Bogartthe code runs fine, but it seems that the way specter defines them makes it hard for kondo to follow correctly#2021-08-0614:00Noah Bogartis there anything i can do to make this work without adding every navigator to my .clj-kondo/config.edn file?#2021-08-0614:00borkdude@nbtheduke https://github.com/redplanetlabs/specter#clj-kondo#2021-08-0614:00Noah Bogartoops, i am ashamed to have missed that lol#2021-08-0614:01Noah Bogartthank you#2021-08-0614:02borkdudeI think this could be added to the clj-kondo.exports part of the specter lib#2021-08-0614:02borkdudethen it would have worked almost automatically#2021-08-0614:02borkdudebut then the maintainer would have to accept that :)#2021-08-0614:02borkdudeSee https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-08-0614:04Noah Bogartthat’s very cool, thank you#2021-08-0614:23dharriganthank you too! added 🙂#2021-08-0614:24borkdudeWhat are you referring to here?#2021-08-0614:25dharriganthe lint-as block#2021-08-0614:26dharriganI'm not part of the spectre team 🙂#2021-08-0614:28borkdudeDo Noah and you work together?#2021-08-0614:28borkdudeI missed that part of the context#2021-08-0614:29dharriganNo, sorry. I should have been more specific. Thank you for the link to the spectre#clj-kondo information. I didn't see that too. I've added that to my clj-kondo config file as well.#2021-08-0614:30borkdudecool#2021-08-0614:29Joshua SuskaloYeah, I added that config a while back @nbtheduke. It may end up eventually needing some more stuff though, so let me know if you run into anything unrecognized or linting weirdly and we can collaborate on that config before making another pr to the repo.#2021-08-0621:06Noah BogartOh wow is specter under your umbrella? #2021-08-0621:27Joshua SuskaloI use it all the time and I contributed that config to the repo, but I'm not a frequent contributor or anything.#2021-08-0614:30Joshua SuskaloAlso @borkdude I asked the author of specter if he wanted to have the config in the artifact and he said no since it increases the size of the artifact (if only slightly) and the number of people who use clj-kondo is still a minority.#2021-08-0614:31borkdudeThen perhaps contributing it to https://github.com/clj-kondo/config is a good second option#2021-08-0614:31borkdudeor just do both#2021-08-0614:32Joshua SuskaloI'd be happy to contribute it there if it'd be accepted.#2021-08-0614:32borkdude(I mean README + clj-kondo/config)#2021-08-0614:32borkdudeor link from README to clj-kondo/config#2021-08-0614:33Joshua Suskalosure#2021-08-0614:34borkdudeanyway, this will always be an issue (being at the mercy of library maintainers), so clj-kondo/config seems like something which is always possible and perhaps clj-kondo itself could look for config over there automatically in the future#2021-08-0614:35borkdudethe nice thing about having the config with the library itself is that the config can be maintained per library version#2021-08-0614:36Joshua SuskaloCould have like a --contrib-configs flag when using --copy-configs that'd check for it in this repo.#2021-08-0614:36borkdudeyeah#2021-08-0614:37Joshua SuskaloThen the repo could become just community-maintained configs that people can use, while still leaving the option for the lib maintainers to publish one that doesn't conflict in the future. I like that idea a lot.#2021-08-0621:08Noah BogartReminds me of DefinitelyTyped, the npm packages that add Typescript definition files for JavaScript libraries. Maybe this could be the same? #2021-08-0621:09borkdudeI've also heard that being mentioned#2021-08-0614:37borkdudeyeah#2021-08-0619:08borkdudeMicro-release with a bugfix and one new feature by @hugod : https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#20210806#2021-08-0621:08Noah BogartReminds me of DefinitelyTyped, the npm packages that add Typescript definition files for JavaScript libraries. Maybe this could be the same? #2021-08-0714:44seriogaHm, updated clj-kondo on windows, there is no output after update...
Updating 'clj-kondo' (2021.06.18 -> 2021.08.06)                            
Downloading new version                                                    
clj-kondo-2021.08.06-windows-amd64.zip (8,9 MB) [==========================
Checking hash of clj-kondo-2021.08.06-windows-amd64.zip ... ok.            
Uninstalling 'clj-kondo' (2021.06.18)                                      
Removing shim for 'clj-kondo'.                                             
Unlinking ~\scoop\apps\clj-kondo\current                                   
Installing 'clj-kondo' (2021.08.06) [64bit]                                
Loading clj-kondo-2021.08.06-windows-amd64.zip from cache                  
Extracting clj-kondo-2021.08.06-windows-amd64.zip ... done.                
Linking ~\scoop\apps\clj-kondo\current => ~\scoop\apps\clj-kondo\2021.08.06
Creating shim for 'clj-kondo'.                                             
'clj-kondo' (2021.08.06) was installed successfully!                       
#2021-08-0714:46seriogalook like doing something but without linting took 1006ms, errors: 0, warnings: 0 on exit#2021-08-0714:54seriogaecho '(select-keys [:a])' | clj-kondo --lint - also without output#2021-08-0714:55borkdude@serioga can you download the Windows binary from the Github releases page and test with that.#2021-08-0714:55borkdudeIf that works, then it could be an issue with scoop itself#2021-08-0714:59seriogamoment#2021-08-0715:05seriogastruggling with “Access denied”...#2021-08-0715:10borkdudeaccess denied where#2021-08-0715:11seriogasame with downloaded clj-kondo-2021.07.28-windows-amd64#2021-08-0715:11borkdudewhere#2021-08-0715:11seriogabut downloaded clj-kondo-2021.06.18-windows-amd64 is ok#2021-08-0715:12serioganot clear “where”
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "a4e5cad3c1cac0c1d6e4f3edeae0ebf3f78996f1e3e3f790e5"}, :content ("[email protected]")}
#2021-08-0715:12borkdudePlease specify exactly what you are doing. From where did you download this binary. Github releases?#2021-08-0715:12seriogayes, from github releases#2021-08-0715:13serioga
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "a1e0cfd6c4cfc5c4d3e1f6e8efe5eef6f28c93f4e6e6f295e0"}, :content ("[email protected]")}
#2021-08-0715:13borkdude@ales.najmann Perhaps you can have a look?#2021-08-0715:14borkdudeI'm not sure why these binaries would fail. Can you look at the file security settings?#2021-08-0715:14seriogabut works with admin privileges
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "88c9e6ffede6ecedfac8dfc1c6ccc7dfdba5baddcfcfdbbcc9"}, :content ("[email protected]")}
#2021-08-0715:15borkdudePerhaps it's your virus scanner#2021-08-0715:15borkdudenot sure#2021-08-0715:15borkdudeor something changed on appveyor#2021-08-0715:15borkdudeor in graalvm#2021-08-0715:15borkdudealso not sure#2021-08-0715:17seriogaso as I see versions higher then 2021.06.18 does not output without admin privileges. at least on this PC#2021-08-0715:17seriogachecking antivirus#2021-08-0715:19seriogaantivirus is off, no changes will check at the office on Monday#2021-08-0715:20borkdudeok, I will try later this weekend on my Windows computer too#2021-08-0717:50littlelithis is my output:
~ $ echo '(select-keys [:a])' | clj-kondo --lint -
<stdin>:1:1: error: clojure.core/select-keys is called with 1 arg but expects 2
linting took 11ms, errors: 1, warnings: 0
#2021-08-0717:50littleliso it seems to be working for ok me if I understand above conversation#2021-08-0720:30ericdalloI realized clj-kondo invalid-aritylinter doesn't work when using a function with partial , is that expected or should I open an issue? 🧵#2021-08-0720:30ericdallo
(defn foo [a b]
  (+ a b))

(foo a) ;; lint correctly

(partial foo 1) ;; no lint
#2021-08-0720:31ericdalloNot sure it's a bug since the function is not being called properly#2021-08-0720:31ericdallois just that this is causing problems to me during some refactors, I'm missing clj-kondo warning for those cases#2021-08-0720:32ericdalloActually, clj-kondo could lint for this case:
(map (partial foo) [1 2 3])
#2021-08-0720:32borkdudeI think clj-kondo could do better here#2021-08-0813:39Drew VerleeMy goal is to see if i can help with some of the clj-kondo open issues. I believe my best bet is first to establish how to run the main functionality so i can what information is returned and how it's used. My intution is that that functionality is contained in clj-kondo.core/run!. Luckily there is even an example in a comment. Is this example still good? I see a files key that doesn't seem to be used by the function https://github.com/clj-kondo/clj-kondo/blob/974540e83401c9c5def1d92cb1d8fc3ae945f736/src/clj_kondo/core.clj#L210#2021-08-0813:40borkdude@drewverlee I think that comment form is stale :). I think your best bet for working examples is the test suite#2021-08-0813:41borkdudeThanks for the intent to help out!#2021-08-0813:42borkdudeI have marked a bunch of tickets as "PR Welcome": https://github.com/clj-kondo/clj-kondo/issues?q=is%3Aissue+is%3Aopen+label%3A%22PR+welcome%22 That doesn't mean that other issues aren't welcome to PR-ed but sometimes a ticket needs more thought/discussion before implementation. The PR welcome tickets are fairly well figured out already.#2021-08-0813:43borkdudeYou can also find some development guidance here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/dev.md#2021-08-0813:45Drew Verleethanks @borkdude ill take a look.#2021-08-0822:45Drew VerleeOne of the things that i'm constantly perplexed by is how often my repl experience breaks or changes from project to project. In this case if i try to eval this file, i'm told that linters/arity-error doesn't exist. https://github.com/clj-kondo/clj-kondo/blob/974540e83401c9c5def1d92cb1d8fc3ae945f736/src/clj_kondo/impl/analyzer.clj#L954#2021-08-0823:07Drew Verlee@borkdude It's hard to tell by looking at the tests where to trace back the code that's being tested. e.g https://github.com/clj-kondo/clj-kondo/blob/master/test/clj_kondo/analysis_test.clj#L22 doesn't explicitly call upon any function (i can tell). Would i be correct in assuming an issue like https://github.com/clj-kondo/clj-kondo/issues/426 might be solved by assing an linter and i should read https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#L1#2021-08-0913:20borkdude@drewverlee For that specific linter, what I would do is look at analyzer.clj if we already have a special case for loop and recur. Then when going into the analysis for loop, add a key with a volatile or so to the ctx which tells us that we are inside of the loop. Then when encountering recur, you put a boolean true in the volatile (given that the volatile is there). Then after analyzing the body of loop, you will know that there was a recur. If not, emit a warning. Something like that.#2021-08-0913:21borkdudeAbout the REPL: don't know what you are doing, but I keep my tooling pretty basic. No magic jack-in so my dependencies are always known and don't upgrade automagically. Just a plain clj REPL + require + :reload also goes a long way I find. Pretty primitive, but this way I can even reload code in a node REPL easily.#2021-08-0913:22borkdudeOther than that, I very often just invoke clj-kondo from the command line with clojure -M:clj-kondo/dev --lint /tmp/example.clj to test out dev stuff#2021-08-0916:10Drew VerleeCorrect me if i'm wrong, But I don't think there is a way to have a clojure project linked to a cider version. As locking down the deps on nrepl, only shift the issue to the emacs cider client. That is why i prefer to not declare a cider version, so that I don't get the emacs client and the cider repl out of sync. E.g if i use your cider deps version i get warnings right away: WARNING: CIDER 1.2.0-snapshot requires cider-nrepl 0.26.0, but you're currently using cider-nrepl 0.22.0-beta4. The version mismatch might break some functionality! (More information) WARNING: clj-refactor and refactor-nrepl are out of sync. Their versions are 2.5.1 (package: <tel:202106281154|20210628.1154>) and 2.5.0-SNAPSHOT, respectively. You can mute this warning by changing cljr-suppress-middleware-warnings. Which means i would have to change the version on my cider emacs client. I'll find a way to work around it, I just wanted to be sure we (I) understood the trade off. As an aside, maybe there should be a way to auto install the matching version on the client?#2021-08-0916:16borkdudeyou can include aliases from your ~/.clojure/deps.edn#2021-08-0916:20Drew VerleeI understand, i did that. Then cider client on emacs complains about the versions you as per the error above. I suppressed the warnings and was able to use debug and some other features, hopefully thats good enough. I don't want to distract from the more important issue. 🙂#2021-08-0916:22borkdudeYou can develop how you like, I just shared how I did it and that may or may not work for you :)#2021-08-0921:43nhamaking my first clj-kondo config 🙂 I am wondering how to resolve some of my macros so the bindings are recognized. They all look similar to this:
(with-something [a bindings & body])
(with-something-else [a b c bindings & body])
I think the idea should be to have the bindings argument in particular be recognized.. I tried something like this
:hooks {:analyze-call {my.ns/with-something macroexpand.one-of/one-of ,,,
but either this does not work or my config is not reloaded (not sure how to trigger that besides restarting spacemacs)
#2021-08-0921:44borkdude@nha to test config I think it's best to invoke clj-kondo from the command line and stick some println in the hook function#2021-08-0921:46nharight, I was hoping there would be something like with-open but where I can tell clj-kondo where is the bindings vector. Will try from the cli#2021-08-0921:47borkdude@nha you might also be able to copy your macros as is into same named namespaces into the config dir#2021-08-0921:47borkdudeand then use the new :macroexpand option#2021-08-0921:47nhaI think that’s what I am doing. Getting a warning from the cli straight away though
....WARNING: file macroexpand/one_of.clj not found while loading hook
#2021-08-0921:48borkdudedid you maybe use a hyphen in the filename instead of underscore? and are these files inside your .clj-kondo dir?#2021-08-0921:49borkdude> macroexpand/one_of.clj is an example from clj-kondo's own codebase btw#2021-08-0921:49nhaaah it’s not built-into kondo then? that would be my error#2021-08-0921:49nhaooh gotcha https://github.com/clj-kondo/clj-kondo/blob/master/.clj-kondo/macroexpand/one_of.clj#2021-08-0921:50borkdudethis config: my.ns/with-something macroexpand.one-of/one-of needs to look like my.ns/with-something your-code/your-macro#2021-08-0921:50nharight, I get it now. I assumed it was built-in. My mistake 🙂#2021-08-0921:54Drew Verlee@borkdude I had some time to look into a solution for the loop-missing-recur issue as previously discussed. its chilling https://github.com/clj-kondo/clj-kondo/compare/master...drewverlee:issue-426-warning-for-a-loop-without-a-recur?expand=1 before i open the PR though i want to do some more work. I was looking at the contribute guidelines at the diff tool and it seems to print out a lot of stuff. Is that still relevant? e.g ./script/diff Maybe its doing what it intended, at a glance it seemed to have more then i though i changed.#2021-08-0921:56Drew Verleealso, is this the right place to ask these questions 🙂#2021-08-0921:56borkdude@drewverlee yeah that's still relevant. it should not output any new warnings#2021-08-0921:56Drew Verleekk. ill double check.#2021-08-0921:56borkdude@drewverlee I think your code looks good, except for one thing, I hinted at above. I don't like to walk ASTs multiple times and do everything as much as possible in one pass.#2021-08-0921:57borkdude(https://clojurians.slack.com/archives/CHY97NXE2/p1628515239199000)#2021-08-0921:59borkdudeyou can do it in the way I hinted there, or there's another way, to inspect all calls to recur and then look up the :callstack, that would perhaps work, I'm not completely sure#2021-08-0921:59borkdudealso one challenge is to verify if the recur you are looking at belongs to the specific loop you're analyzing#2021-08-0922:00borkdudeit could also be an inner anonymous function for example#2021-08-0922:00borkdudeI'll be back tomorrow for more questions. Nice work so far#2021-08-0922:02Drew VerleeThanks, good observations. I'll have to tackle them tomorrow to.#2021-08-1415:21AJ JaroI’m just starting to get into clj-kondo and really like it so far! Is it possible that clj-kondo can resolve function names that a macro produces? For example, I have a macro create-utils that generates a set of standard functions like save! and for-id. I tried using the macroexpand utility and I couldn’t get that to work, but I’m not sure if this behavior is possible to resolve with clj-kondo. Could I reference save! or for-id from another namespace and have it resolve successfully? Example:
(ns db.core
 (:require [db.util :as util])

(util/create-utils)
(ns db.test
 (:require [db.core :as core])

(defn get-data []
  (core/for-id 1))
#2021-08-1415:22borkdude@ajarosinski example seems incomplete?#2021-08-1415:24AJ JaroI accidentally hit the wrong enter button!! In the example above, I am having trouble resolving for-id in db.test#2021-08-1415:24borkdudewhat you can do here is use the macroexpand feature to expand into (do (def for-id ..) )#2021-08-1415:24borkdudeor just (declare for-id ...)#2021-08-1415:25AJ JaroHmm, ok. I will give it another go! Thanks @borkdude#2021-08-1415:25borkdudeLet me know when you get stuck, I'm 100% sure this can work :)#2021-08-1415:26borkdudeIn doubt, stick a println in your macro to see if it gets executed#2021-08-1415:26borkdudeand execute clj-kondo from the command line#2021-08-1415:26AJ JaroThat’s the confirmation I needed before I spent a ton of time on it. I really appreciate your support in this channel; it’s downright impressive#2021-08-1420:52AJ JaroWelp, it of course turns out to be user error. It helps a lot of I upgrade to the proper version! :face_palm:#2021-08-1420:54borkdudeah yes, it's a new feature :)#2021-08-1420:54borkdudePerhaps we should add that to the docs#2021-08-1420:58AJ JaroMeh, I don't know. I definitely knew it was a new feature. Just silliness#2021-08-1518:03lread@borkdude, as promised in #lsp, raised issue https://github.com/clj-kondo/clj-kondo/issues/1353.#2021-08-1518:06borkdudeThanks!#2021-08-1620:06lread@borkdude, small weirdness with script/diff🧵#2021-08-1620:09lread
git clone 
cd clj-kondo
script/diff
returns an expected:
Linting and writing output to /tmp/clj-kondo-diff/branch.txt
Cloning into 'clj-kondo'...
remote: Enumerating objects: 12371, done.
remote: Counting objects: 100% (1395/1395), done.
remote: Compressing objects: 100% (598/598), done.
remote: Total 12371 (delta 761), reused 1172 (delta 692), pack-reused 10976
Receiving objects: 100% (12371/12371), 11.82 MiB | 1.93 MiB/s, done.
Resolving deltas: 100% (7142/7142), done.
Linting and writing output to /tmp/clj-kondo-diff/master.txt
2558c2558
< linting took 11494ms, errors: 264, warnings: 2293
---
> linting took 11589ms, errors: 264, warnings: 2293
but if I run script/diff a second time I get:
Linting and writing output to /tmp/clj-kondo-diff/branch.txt
Cloning into 'clj-kondo'...
remote: Enumerating objects: 12371, done.
remote: Counting objects: 100% (1395/1395), done.
remote: Compressing objects: 100% (598/598), done.
remote: Total 12371 (delta 761), reused 1172 (delta 692), pack-reused 10976
Receiving objects: 100% (12371/12371), 11.82 MiB | 3.03 MiB/s, done.
Resolving deltas: 100% (7142/7142), done.
Linting and writing output to /tmp/clj-kondo-diff/master.txt
1923c1923
< clojure/tools/reader.clj:18:53: warning: use alias or :refer [char desugar-meta ex-info? namespace-keys numeric? reader-conditional second' tagged-literal whitespace?]
---
> clojure/tools/reader.clj:18:53: warning: use alias or :refer [char desugar-meta ex-info? namespace-keys numeric? second' whitespace?]
2173c2173
< inlined/clj_kondo/impl/toolsreader/v1v2v2/clojure/tools/reader.clj:16:87: warning: use alias or :refer [char desugar-meta ex-info? namespace-keys numeric? reader-conditional second' tagged-literal whitespace?]
---
> inlined/clj_kondo/impl/toolsreader/v1v2v2/clojure/tools/reader.clj:16:87: warning: use alias or :refer [char desugar-meta ex-info? namespace-keys numeric? second' whitespace?]
2558c2558
< linting took 11885ms, errors: 264, warnings: 2293
---
> linting took 11884ms, errors: 264, warnings: 2293
If I rm -rf .clj-kondo/.cache and re-run script/diff all is good again, but subsequent runs of script/diff will again return the unexpected result.
#2021-08-1620:13lreadCan GitHub issue this if that makes sense, lemme know.#2021-08-1620:23borkdudeyeah, I've seen this before, nothing to worry about here#2021-08-1620:27lreadThanks, would it make sense to rm -rf .clj-kondo/.cache in script/diff to avoid confusing contributors? Or maybe that’s not a good thing to do. Dunno.#2021-08-1620:28borkdudeI think that would be good to add#2021-08-1620:29lreadGreat, will do a very tiny PR for it - unless you beat me to it.#2021-08-1620:32borkdudeI'm on very slow internet in some East German town right now, so I'm pretty easy to beat right now.#2021-08-1620:50lreadHa! Happy to do it! I’ll create git issue with above for posterity, and then PR.#2021-08-1815:25ericdalloHow can I run clj-kondo in a lein alias to lint the depedencies of my project? 🧵#2021-08-1815:25ericdalloI tried something like this:
"clj-kondo-deps"  ["run" "-m" "clj-kondo.main" "--copy-configs" "--dependencies" "--config" ".clj-kondo/config.edn" "--lint" ~#(clojure.string/join ":" (leiningen.core.classpath/get-classpath %))]
            "clj-kondo"       ["do" ["clj-kondo-deps"] ["run" "-m" "clj-kondo.main" "--config" ".clj-kondo/config.edn" "--lint" "src" "test"]]
#2021-08-1815:25borkdudethis is documented in the README of clj-kondo#2021-08-1815:25ericdallothen lein clj-kondo would first lint the classpath and then the project#2021-08-1815:25borkdudeyou have to use --lint $(lein classpath)#2021-08-1815:26ericdallothe docs only say running from cli, not from lein aliases#2021-08-1815:26borkduderight, I'm not sure, haven't used it that way yet#2021-08-1815:26borkdudeI think that would have to run as a lein plugin then#2021-08-1815:26ericdalloyeah, $(lein classpath) inside lein project.clj would fall into a infinte loop hehe#2021-08-1815:27ericdalloyeah that's what I thought, is there any clj-kondo lein plugin?#2021-08-1815:27borkdudedon't think so#2021-08-1815:28borkdudehaven't you made such a plugin for clojure-lsp?#2021-08-1815:28ericdalloI tried ~#(clojure.string/join ":" (leiningen.core.classpath/get-classpath %)) that lein would eval that, but it returns a function not a string#2021-08-1815:28ericdalloyes#2021-08-1815:28borkdudetry #=(....)#2021-08-1815:28ericdallooh, didn't know about that one, let me try#2021-08-1815:33ericdallodoesn't seems to work 😕#2021-08-1815:44borkdudebut why not implement a proper plugin? why do you need this?#2021-08-1815:45ericdalloa plugin would solve the issue#2021-08-1815:46ericdallobecause at nubank we have this lein clj-kondo alias for all services, but it's missing lint the classpath before to copy the configs and dependencies to cache#2021-08-1815:46borkdudecool. we could host the plugin under the clj-kondo organization#2021-08-1815:47borkdudeand I'll give you the access so you can push there if you want#2021-08-1815:47ericdalloLGTM 🙂#2021-08-1815:47borkdudewhat should the name of the repo be, lein-plugin?
#2021-08-1815:47ericdalloI'd suggest lein-clj-kondo#2021-08-1815:48borkdudeok#2021-08-1815:49borkdudeyou're the admin of https://github.com/clj-kondo/lein-clj-kondo#2021-08-1815:50ericdallothanks, I'll work to have something similar to clojure-lsp lein plugin#2021-08-1816:12ericdalloDo you think the plugin should call clj-kondo.core/run! or clj-kondo.main/main ? if the former, the api for the plugin would look something like:
lein clj-kondo "{:lint "src" ...}"
this would need almost none maintaince to the plugin as it'll be really simple just calling the kondo api, but a less friendly user UX the other one, would looks:
lein clj-kondo --lint src 
but I'm not sure how the lint classpath would work :thinking_face:
#2021-08-1816:14ericdalloactually, I'm not sure how we would solve the classpath issue in the plugin#2021-08-1816:14ericdallooh, actually it's easy, it's just call lein classpath ns#2021-08-1816:16ericdallowe just need probably to parse a specific flag to know we should get the classpath#2021-08-1816:17ericdalloso maybe use the clj-kondo.main/main seems the best approach#2021-08-1816:17ericdallojust adding a interceptor layer to check if the arg to lint is a "$classpath" or something like that#2021-08-1816:25borkdudedo people normally configure lein plugins in EDN?#2021-08-1816:25ericdalloI don't think so#2021-08-1816:55ericdalloJust pushed a working version to master, LMK if you think we should change anything#2021-08-1816:55ericdallootherwsie we can release a initial version with make tag 0.1.0#2021-08-1816:56ericdallo(we can change the release process as you want as well)#2021-08-1816:56ericdalloalso, the artifact is clj-kondo/lein-clj-kondo , not sure if that group-id is correct though#2021-08-1817:09borkdudeI would prefer it if you used babashka tasks instead of Make ;)#2021-08-1817:10ericdallohaha I thought you would say that#2021-08-1817:10ericdalloyeah, I can change it 🙂#2021-08-1817:10ericdallohow do you think the release task would look?#2021-08-1817:10borkdudeI'll get back to you after dinner#2021-08-1817:51ericdalloDone! looks better indeed, babashka rocks#2021-08-1817:51ericdalloLMK what you think#2021-08-1818:24borkdudeThat's better :) Probably a typo here: https://github.com/clj-kondo/lein-clj-kondo/blob/48c30a2059b0127862cc36b42c1f9d4516630ae0/scripts/lein_clj_kondo/ci.clj#L24#2021-08-1818:24ericdalloyep, fixing ...#2021-08-1818:25ericdallodone!#2021-08-1818:28borkdudehere is an example repo of clj-commons: https://github.com/clj-commons/infra it uses a bb script as well to push a tag#2021-08-1818:29borkdudebut I think you already have everything you need#2021-08-1818:29borkdudeso what's next?#2021-08-1818:29ericdallooh good to know#2021-08-1818:30ericdalloif everything looks fine we can bb tag 0.1.0#2021-08-1818:30ericdalloand then bb deploy#2021-08-1818:30ericdallothe last one would need clojars credentials, so I think you need to do this#2021-08-1818:31ericdalloBTW, can you confirm if you have a verified group of clj-kondo on clojars?#2021-08-1818:31ericdallosince clj-kondo is a little bit old project, the group restriction was not need in the time for clojars#2021-08-1818:32borkdudeI have the group, but even if you have the group, you can't push any new projects to it#2021-08-1818:32borkdudeonly existing ones#2021-08-1818:32ericdallooh yeah#2021-08-1818:32borkdudeso I'll make a new one ok#2021-08-1818:32ericdalloI just saw it:#2021-08-1818:32borkdudewith the com.github#2021-08-1818:32ericdalloyeah, we need to update project.clj so#2021-08-1818:32ericdalloand pom.xml#2021-08-1818:33borkdudeoh crap, this is linked to github accounts right#2021-08-1818:33borkdudeso we have to go through some process?#2021-08-1818:33ericdalloyeah hahah you will need to open an PR#2021-08-1818:34ericdallohttps://github.com/clojars/administration/issues/105#2021-08-1818:34ericdallowe need to open that issue but first create the repo or the name of who is opening the issue#2021-08-1818:43borkdude@UKFSJSM38 opened it here: https://github.com/clojars/administration/issues/131#2021-08-1818:43borkdudelet's wait for them to respond#2021-08-1818:44ericdalloPerfect, thank you!#2021-08-1818:48borkdudeSo what is interesting about the clj-commons infra setup is that you can push a tag#2021-08-1818:48borkdudeand then the CI will deploy#2021-08-1818:48borkdudeso we need only one deploy token for whoever can push the tag#2021-08-1818:48borkdudewhich lives in CI#2021-08-1818:48borkdudeperhaps we can set that up?#2021-08-1818:49ericdalloyeah, I have that for clojure-lsp#2021-08-1818:49borkdudecool#2021-08-1818:49ericdallodo you have a example of a project using the clj-commons infra ?#2021-08-1818:49borkdudeyeah lemme check#2021-08-1818:49borkdudethis doesn't use infra but it responds to the tag change: https://github.com/clj-commons/clj-yaml#2021-08-1818:50ericdalloyeah, that could work#2021-08-1818:51ericdallobut what function from infra we want to use to deploy to clojars?#2021-08-1818:51borkdudewe can just run lein deploy clojars#2021-08-1818:52ericdallooh, ok, and setup the clojars credentials using github secrets, right?#2021-08-1818:52ericdallo(that's how I do for clojure-lsp)#2021-08-1818:52borkdudeyes, or circleci secrets#2021-08-1818:52borkdudeif your clojure-lsp setup works you can just re-use that as well#2021-08-1818:53ericdallo👍 alright, I'll work to do the deploy on CI instead of manually#2021-08-1818:53borkdudeyay#2021-08-1819:21ericdalloJust pushed, it uses this action I use on clojure-lsp as well to deploy t oclojars: https://github.com/marketplace/actions/publish-to-clojars so it's a really simple action#2021-08-1819:22ericdallowe just need to setup those 2 secrets on the clj-kondo org or on lein-clj-kondo repositoy#2021-08-1819:22ericdallo
CLOJARS_USERNAME
CLOJARS_PASSWORD
#2021-08-1819:22borkdudeok, I will do that, once I get the group#2021-08-1819:23borkdudechicken and egg, I can't make a token without the group#2021-08-1819:23ericdallohahaha true#2021-08-1819:51ericdalloI can't access the public created repository: https://github.com/clj-kondo/clojars-verification-borkdude :thinking_face:#2021-08-1819:52ericdalloIs that really public?#2021-08-1820:01borkdudea sorry, made it public#2021-08-1913:04ericdalloThe group was verified, LMK when the secrets on Github were configured properly so I (or you) can release the tag#2021-08-1913:44borkdudeyes, I'm seeing it.#2021-08-1913:55borkdudeI'm looking into how I can make a deploy token for this new group#2021-08-1913:55borkdudeI don't see the group in the list for making a deploy token, I'll ask toby#2021-08-1909:34flowthingI'm helping out a colleague with Calva's clojure-lsp integration. They use Windows, and it's not working. Here's the error we see in clojure-lsp.out: https://github.com/BetterThanTomorrow/calva/issues/1050#issuecomment-824719118 The stack trace points to this bit in clj-kondo: https://github.com/clj-kondo/clj-kondo/blob/b6f76ea8371d2497ed14314cf99a679e41f5db4f/src/clj_kondo/impl/core.clj#L358-L360 Sadly, the error message doesn't show the path of the file it's trying to access, so we don't know what the problem is. In any case, I figured we could work around the problem by setting {:output {:canonical-paths false}} in the clj-kondo config, but that doesn't seem to make any difference. It's as though the config isn't getting picked up at all. At least I don't see how .getCanonicalPath is called if :canonical-paths is false. Would it be possible for clj-kondo to log the file it's trying to access so that it ends up in clojure-lsp.out? Any other ideas on how to troubleshoot the issue? The only thing I can think of is to create a custom clj-kondo version that logs the file path, then create a custom clojure-lsp version that includes the custom clj-kondo version, then try to set up Calva to use that. I guess we'll try that if nothing else pans out.#2021-08-1911:01borkdudeCurrently afk but this might mean there is some weird path on your classpath#2021-08-1911:12flowthingCould be, but inspecting the output of (System/getProperty "java.class.path") doesn't reveal anything.#2021-08-1911:20flowthingAnyway, I guess that's sort of the problem. There's a weird path-related issue, but I can't figure out what it is. It doesn't seem to be Could clj-kondo maybe log those file paths using a debug/trace log level?#2021-08-1911:35borkdudeNormally you should get this as a lint warning but not if there is something wrong while producing the lint warning #2021-08-1911:36borkdudeI guess that’s what’s happening #2021-08-1911:36flowthingYeah.#2021-08-1911:38borkdudeYou could try linting using clj-kondo on the command line or JVM and see if you can reproduce this #2021-08-1911:39borkdudeAlso make sure you’re using the newest LSP#2021-08-1911:40flowthingHmm, is it possible to tell Calva to use a different clojure-lsp…? Need to look into it.#2021-08-1911:40flowthingYeah, could try reproing on the command line too. :thumbsup::skin-tone-2:#2021-08-1912:01flowthingCan't repro on the command line.#2021-08-1912:19borkdudeYes, it’s possible but perhaps they automatically use the newest already nowadays#2021-08-1912:19borkdudePerhaps you can see which classpath LSP is using to call clj-kondo #2021-08-1912:20borkdudeIn the logs #2021-08-1912:27borkdude@UKFSJSM38 perhaps you have a hint?#2021-08-1912:36ericdalloClojure-lsp just pass the return of lein classpath to clj-kondo, you can try running that with the -NoProfile like said in the issue and get the output#2021-08-1912:37ericdallopowershell.exe -NoProfile lein classpath#2021-08-1912:49flowthingHmm... actually, clojure-lsp.out has:#2021-08-1912:49flowthing
2021-08-19T12:41:42.131Z SOLPF2AKCBN INFO [clojure-lsp.crawler:20] - Finding classpath via `powershell.exe -NoProfile npx shadow-cljs classpath`
2021-08-19T12:41:51.213Z SOLPF2AKCBN INFO [clojure-lsp.crawler:118] - Analyzing classpath for project root C:\Users\foo.bar-baz\Coxa\piso
2021-08-19T12:41:51.214Z SOLPF2AKCBN INFO [clojure-lsp.kondo:125] - Analyzing 265 paths with clj-kondo with batch size of 6 ...
2021-08-19T12:41:51.214Z SOLPF2AKCBN INFO [clojure-lsp.kondo:131] - Analyzing 1/6 batch paths with clj-kondo...
2021-08-19T12:42:02.513Z SOLPF2AKCBN INFO [clojure-lsp.kondo:131] - Analyzing 2/6 batch paths with clj-kondo...
#2021-08-1912:50flowthingSo maybe it's the classpath that npx shadow-cljs classpath returns that's the problem?#2021-08-1912:51flowthingHmm...#2021-08-1912:52ericdalloyes, probably, if your project is both a lein and npx one, clojure-lso will scan the lein classpath first and then the npx one and merge it#2021-08-1912:52ericdalloso try to run powershell.exe -NoProfile npx shadow-cljs classpath and check the output#2021-08-1912:54flowthingHa! Found the issue, finally! Thanks for the hints, they led us down the right track. 🙂#2021-08-1912:55ericdalloNice, what was the issue?#2021-08-1912:55flowthing
PS C:\Users\foo.bar-baz\Coxa\piso> powershell.exe npx shadow-cljs classpath

------------------------------------------------------------------------------

   WARNING: shadow-cljs not installed in project.

   See      

------------------------------------------------------------------------------

shadow-cljs - config: C:\Users\foo.bar-baz\Coxa\piso\shadow-cljs.edn    

dev/src;dev/resources;target/shadow-cljs;
#2021-08-1912:56flowthingnpx shadow-cljs classpath prints a warning if shadow-cljs isn't installed locally (into the project node_modules.#2021-08-1912:56flowthingThe warning gets fed to clj-kondo.#2021-08-1912:56flowthingnpm install -D shadow-cljs fixes the issue.#2021-08-1912:56ericdallohummm, good to know, we can change the default on clojure-lsp adding that flag if that makes sense#2021-08-1912:57flowthing(Our projects use the shadow-cljs Clojure API, so we don't typically install shadow-cljs via NPM.)#2021-08-1912:57ericdallofeel free to open an PR changing it https://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/crawler.clj#L61#2021-08-1912:57flowthingI don't know that there's a flag that hides the warning.#2021-08-1912:58ericdallohum, so I think we can improve the way clojure-lsp handles that, probably shadow-cljs prints to output that, but it's not the return of the command#2021-08-1912:58ericdallowe should only listen to the return of the command#2021-08-1912:59flowthingYeah, I'm not sure whether shadow-cljs prints that warning into stderr or stdout.#2021-08-1912:59ericdallocould you create a simple repro project where you confirm that happens so I can try debug it later?#2021-08-1912:59ericdalloexactly, it should print to stderr I think#2021-08-1912:59flowthingYeah, if it does, then it should be a relatively easy fix.#2021-08-1912:59flowthingSure, I'll create an issue.#2021-08-1912:59ericdalloanyway, we can improve clojure-lso to get only the last line of the output#2021-08-1913:01ericdallotesting on a lein project, lein also prints a lot of thinks specifally if the :pedantic flag is :warn, but that work with clojure-lsp becaause probably lein prints only the classpath to stdout#2021-08-1913:04flowthingNo, shadow-cljs sadly prints the warning into stdout.#2021-08-1913:05ericdalloyeah, I think the best option is to change clojure-lsp to only get the last line of the output as the classpath#2021-08-1913:05flowthing
λ npx shadow-cljs classpath 2>/dev/null
------------------------------------------------------------------------------

   WARNING: shadow-cljs not installed in project.
   See 

------------------------------------------------------------------------------
dev/src: <SNIP>
#2021-08-1913:06flowthingYeah, that might be the quickest fix, although could maybe also ask Thomas to fix that in shadow-cljs.#2021-08-1913:07ericdalloyeah, both sounds good 🙂#2021-08-1913:29flowthingHeh, and just to emphasize that this only occurs on Windows, because at least macOS doesn't have a problem with a path that looks like ------------------------------------------------------------------------------\n\n WARNING….#2021-08-1913:29flowthing
λ clj -M -e '(.getCanonicalPath ( (first (clojure.string/split (slurp "/tmp/foo.txt") #":"))))'
"/private/tmp/lsp-shadow-cljs/------------------------------------------------------------------------------\n\n   WARNING"
#2021-08-1913:43borkdudeok, so there should be a try catch around canonical path as well in clj-kondo?#2021-08-1913:44ericdalloprobably @U04V15CAJ!#2021-08-1913:44ericdalloa warning log from kondo when parsing those cases sounds good#2021-08-1913:46borkdude@U4ZDX466T ok, can you raise an issue before I forget?#2021-08-1914:06flowthingYeah, can do, unless I forget first. 🙂#2021-08-1914:43borkdudeok, I pushed this one: https://github.com/clj-kondo/clj-kondo/commit/472d1417b504e2f4e91c7e8ec092436926327ac3#2021-08-1922:28ericdalloFYI @U4ZDX466T https://github.com/clojure-lsp/clojure-lsp/issues/523#2021-08-2001:48ericdalloAvailable on next clojure-lsp release#2021-08-2005:16flowthing@UKFSJSM38 Awesome, many thanks! I also created an issue for shadow-cljs, so it'll probably get fixed there, too. Maybe it's enough to fix it in three places. 😛#2021-08-1920:45ericdalloI have an improvement suggestion that I'd like to know if that makes sense to be done on clj-kondo 🧵#2021-08-1920:47ericdallorelated to midje , there is a macro midje.sweet/provided that is used to mock function calls, and it's possible to pass a & anything to suppress any extra args, for example:
(fact "foo"
  (my-func) => true
  (provided
    (other-func & anything) => 2))
this should mock other-func call and it doesn't care about the args. clj-kondo reports the other-func as wrong arity, it's possible to make clj-kondo ignore that linter if the args is a & anything ?
#2021-08-1920:48ericdalloATM we are always exlcluding this with {:linters {:invalid-arity {:exclude [(midje.sweet/provided [*])]}}} but that looks not ideal and needs extra configuration#2021-08-1921:11borkdudeif you remove the [*] it will exclude all calls within the provided macro#2021-08-1921:13ericdalloyeah, but imagine there is a valid call that I want to clj-kondo lint as invalid arity:
(provided
  (foo & anything) => 1 ; don't care about the invalid-arity
  (bar 1 2 3) => 2)     ; I do want a invalid-arity here 
#2021-08-1921:13ericdallodoes that makes sense?#2021-08-1921:14borkdudeit does make sense, you can support this by writing an analysis hook or macroexpand hook#2021-08-1921:15ericdalloyou mean, we could add a config on midje lib of:
{:linters {:invalid-arity {:exclude [(midje.sweet/provided)]}}}
but with a custom analysis hook to do lint the invalid-arity if not & anything ?
#2021-08-1921:18borkdudeI would remove the invalid-arity config and just handle this from your hook. expand into a call to the function if it doesn't contain an ampersand, and expand into a non-call like [foo anything] in the case of an ampersand, so clj-kondo will still see that the function is being used, and the arguments, but it won't be treated as a call#2021-08-1921:20ericdalloI don't thing I get it :thinking_face:#2021-08-1921:23borkdudeok, well, this:
(provided
  (foo & anything) => 1 ; don't care about the invalid-arity
  (bar 1 2 3) => 2) 
would expand into:
(do 
  [foo anything] 1 ; don't care about the invalid-arity
  (bar 1 2 3) 2))
for example
#2021-08-1921:43ericdallouhm, I see, looks a good idea#2021-08-1920:46dominicmUsing the clj-kondo api, how can I specify a hook to be used? It's already in a directory. I tried setting :config-paths, but had no luck.#2021-08-1920:49ericdalloclj-kondo check your projec config and check for :config-paths first, if a config path of foo/bar is found, then it tries to find in your project a .clj-kondo/foo/bar/config.edn file#2021-08-1920:49ericdalloif that folder doesn't exists it's because clj-kondo didn't import the folder, you can make that work with something like:#2021-08-1920:50ericdallo
clj-kondo --copy-configs --dependencies --lint $(lein classpath)
#2021-08-1920:50ericdallothen clj-kondo will analyze the classpath, copy the folders from other libs classpaths and then you just need to have your :config-paths configured correctly#2021-08-1920:51ericdalloA concrete example of rewrite-clj config paths on clojure-lsp: https://github.com/clojure-lsp/clojure-lsp/blob/master/.clj-kondo/config.edn#L1#2021-08-1920:51ericdallonote that is recommended to commit that folder inside the .clj-kondo dir after clj-kondo copy the configs#2021-08-1920:55dominicmI'm using the API, I want to analyze another project that I am not in the cwd of from the JVM.#2021-08-1920:56ericdalloyou can still use those flags via API, similar to how clojure-lsp uses https://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/kondo.clj#L82-L89#2021-08-1920:56ericdallobut you will need to pass the classpath manually like clojure-lsp gets manually the classpath#2021-08-1920:57ericdalloor pass the path to your external lib if that makes sense to you#2021-08-1921:04borkdudeLet's take a step back. I don't think dominic is asking how you import a config. he already has the hook config#2021-08-1921:05borkdudeThe way to enable that is in the :hooks config, as documented here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-08-1921:06borkdudeOr is the config imported from another library? Then adding it to the config-paths should work#2021-08-1921:06borkdudeNeed more info. Show the directory structure for example#2021-08-1921:07ericdallo> Or is the config imported from another library? Then adding it to the config-paths should work Unless there is no cache, so clj-kondo would not find the hook I think#2021-08-1921:07borkdude.clj-kondo dir you mean#2021-08-1921:08borkdudethis is why I need the directory structure#2021-08-1921:08dominicmI have a .clj-kondo dir containing a "config.edn" and a "hooks". It belongs to projectA.#2021-08-1921:08dominicmI'm in projectB (totally unrelated, but performing analysis on projectA). I'd like to utilize those hooks.#2021-08-1921:09borkduderight and those configs are "closed source" let's say?#2021-08-1921:10borkdudea mono-repo situation?#2021-08-1921:11dominicmYes, closed source. But not a mono-repo situation. ProjectB may be open sourced. I'm perfoming visualizations on namespaces using d3.#2021-08-1921:11dominicmThe hooks work, no problem there. I use them for linting.#2021-08-1921:12borkdudeyou could put those hooks in a third directory with a config.edn + the hook code#2021-08-1921:12borkdudeand then refer to that from both projects using config-paths#2021-08-1921:14dominicmThey're already in a directory named .clj-kondo. I tried using :config-paths and didn't get the hooks factored in.#2021-08-1921:15dominicm
(kondo/run!
    {:lint ["/full/path/to/file/src/foo/bar/baz.cljs"]
     :config {:output {:analysis true
                       :config-paths ["/full/path/to/file/.clj-kondo"]}
              :config-paths ["/full/path/to/file/.clj-kondo"]}
     :config-paths ["/full/path/to/file/.clj-kondo"]})
I really tried to use it 😄
#2021-08-1921:15borkdudeconfig-paths should go into your project's .clj-kondo/config.edn#2021-08-1921:16borkdudenot sure if it works with run! (could work, but not sure)#2021-08-1921:18dominicmprojectA or projectB?#2021-08-1921:24borkdudewell, as I said, I would put the (shared) config in a third directory#2021-08-1921:24borkdudeand then add that third directory to :config-paths in both projects#2021-08-1921:25borkdudeor you could use the import/export mechanism is projectA is a proper dependency#2021-08-1921:25dominicmOh, and it would be in config.edn :config-paths, rather than with run!#2021-08-1921:25borkdudeyeah#2021-08-1921:25borkdudealthough it might work with run!, I've never really used it like that#2021-08-1921:25dominicmIt doesn't seem to so far.#2021-08-1921:25borkdudeyou can use relative paths in config-paths as well#2021-08-1921:41dominicmMaybe the more obvious solution, should I just slurp the config.edn in .clj-kondo/ ?#2021-08-1921:42dominicmhm, no. Because the hooks won't be resolved relatively in the way I want.#2021-08-1921:43dominicmIdeally this would work without needing cwds, so I could build something like https://next.github.com/projects/repo-visualization without cloning full repos.#2021-08-1921:44borkdudehooks are resolved relative to their config.edn file#2021-08-1921:44borkdudeif you say: config-paths ["other-dir"]#2021-08-1921:45borkdudeand you have other-dir/config.edn + other-dir/hooks/code.clj#2021-08-1921:45borkdudethen you can refer from other-dir/config.edn to the code directly#2021-08-1922:14dominicmIs there any other way to provide hooks? As literals somehow?#2021-08-1922:14dominicm(no files)#2021-08-1922:15ericdalloyes, you can pass as code, there is a example on clj-kondo repo, let me check#2021-08-1922:15ericdallohttps://github.com/clj-kondo/clj-kondo/blob/master/test/clj_kondo/hooks_test.clj#L57#2021-08-1922:15ericdalloyou can pass it as string#2021-08-1922:15borkdudeehm, that's not really intended to be exposed to users, it's only done for testing ;)#2021-08-1922:16ericdalloyeah not sure why you would do that way#2021-08-1922:17borkdudeI'm going to sleep now#2021-08-2010:00dominicm#2021-08-2010:00dominicmHere's what I'm doing with kondo btw 🙂#2021-08-2010:00dominicmI'd also like to do something similar for to tools.deps.graph#2021-08-2010:16borkdudecool. so if you need additional help, I think it would be good to make a small minimal dummy repro so we have something concrete to talk about and debug instead of guessing#2021-08-2010:22dominicmI think you've answered my question, which is, it's not possible to pull hooks in from another directory at the moment.#2021-08-2010:22dominicmIf I continue to be excited about this project, I'd like to explore changing that in kondo somehow.#2021-08-2010:23dominicmIdeally I can load this data from github via http, and allow users to just type in "juxt/clip" or whatever, and get an analysis of namespaces. Similar to how https://next.github.com/projects/repo-visualization works#2021-08-2010:24borkdude> it's not possible to pull hooks in from another directory at the moment I haven't said this isn't possible.#2021-08-2010:26borkdudebut your use case would be better off with a repro, so we can talk about code instead of guessing. it is possible to get hooks from other places#2021-08-2010:28borkdudethis may also work for your use case: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration but since your code is closed source, I can't really offer any help beyond guesswork which isn't very productive#2021-08-2010:29borkdudeyou could also hire me for a few hours to do some consulting for your company if that's easier for you ;)#2021-08-2018:50ericdalloI have a false-positive from clj-kondo that I'd like to understand if it's an issue or not 🧵#2021-08-2018:52ericdallo
(ns foo
  (:require
   [clojure.string :refer [split-lines]])) ;; gives unused-namespace + unured-reffered-var

#?(:clj
   (split-lines ""))
#2021-08-2018:53ericdalloIf I move the require to a #?(:clj ) it works, but that way should work as well, right?#2021-08-2018:59ericdalloclojure-lsp removes the require from ns when the require is unused, this kind of issue could be really bad for clojure-lsp clean-ns feature 😕#2021-08-2019:24borkdudeI see the problem, but I think the analysis info provides enough info for the clean-ns to not remove this: e.g. one usage is enough to not clean it#2021-08-2019:25borkdudefrom the clj-kondo perspective: the linting happens twice, once for the clj branches and once for the cljs branches#2021-08-2019:25ericdalloyeah, but it seems a workaround right? fix the root issue seems the right choice?#2021-08-2019:25ericdalloeven if we fix on clojure-lsp, it's still a warning on clj-kondo that is a false-positive 😕#2021-08-2019:25ericdallo> from the clj-kondo perspective: the linting happens twice, once for the clj branches and once for the cljs branches Is that easy to fix?#2021-08-2019:26ericdalloShould I open an issue?#2021-08-2019:26borkdudeno, this is not an issue, it is just how it works and how it has always works: it's intended#2021-08-2019:26ericdallo😮 even if it's a valid used code, is it right report as unused?#2021-08-2019:27borkdudeit is unused in cljs. there's an issue to add to the linting "cljs" so it's more clear#2021-08-2019:27ericdallooh, got it#2021-08-2019:28borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1196#2021-08-2019:29ericdalloI see#2021-08-2019:29ericdalloI would prefer not to check the analysis for performance reasons as ATM we are only relying on findings#2021-08-2019:29ericdalloWe would need to rely on analysis only because of this specific case#2021-08-2019:30borkdudewe can add some more info to the findings perhaps: a lang key#2021-08-2019:30borkdudeand if there are not two the same findings for both languages, you should not remove?#2021-08-2019:31ericdallohum, maybe#2021-08-2019:31borkdudeor we can enhance the unused-* linters to behave the way you expected them#2021-08-2019:32borkdudewith a setting#2021-08-2019:32ericdalloyeah, that would be the perfect from clojure-lsp view, but that other idea of enhance the findings would work as well I think#2021-08-2021:41borkdudewith the enhanced findings you would not be depending on what the user would configure, so that seems more stable right?#2021-08-2021:43ericdalloExactly#2021-08-2021:51borkdudeanother thing to look out for is when we will change the message to include the language (clj or cljs) then LSP should only look at other fields like :lang and :ns and :name perhaps#2021-08-2021:51borkdudeI'm not sure if we already include those#2021-08-2021:52borkdudeare you depending on the exact format of the message in some cases? I hope not?#2021-08-2021:57ericdalloNo, only the code#2021-08-2021:58ericdalloinvalid-arity for example#2021-08-2021:58ericdallohttps://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/feature/code_actions.clj#L39-L41#2021-08-2022:10borkdudecool#2021-08-2022:11borkdudeHey, what's the easiest way to setup neovim with clojure-lsp? neovim now has the lsp client built in right?#2021-08-2022:11borkdudeI want @U051N6TTC to try out clojure-lsp ;)#2021-08-2022:11ericdalloYes, It has it built-in, but I don't know anything from nvim side besides that :/#2021-08-2022:12borkdudePerhaps @U11EL3P9U knows?#2021-08-2022:12ericdalloHe needs to install clojure-lsp, first, this is what I know hahaha#2021-08-2022:12borkdudequoll = she#2021-08-2022:12ericdalloI think he uses CoC#2021-08-2022:13ericdalloMaybe @UMMMKKADU knows, he uses nvim#2021-08-2022:13ericdalloShe can check this: https://clojure-lsp.github.io/clojure-lsp/clients/#vim#2021-08-2022:17rafaeldelboniI'm using a super fancy nvim/fennel setup, but as @UKFSJSM38 said Nvim 0.5 has a built-in LSP and you just need a plugin to setup which is this one: https://github.com/neovim/nvim-lspconfig#2021-08-2022:18rafaeldelboniThis in company of https://github.com/hrsh7th/nvim-compe for auto completion and https://github.com/nvim-telescope/telescope.nvim#neovim-lsp-pickers for fancy menus and pickers is all you need#2021-08-2022:19ericdalloThanks, we really need a tutorial mentioning all of that :p#2021-08-2022:20rafaeldelbonicoc-nvim bundles all of this in one, but is written in nodejs, people is jumping out#2021-08-2022:20rafaeldelboniHahaha I will, I just migrated for the native stuff, but you right.#2021-08-2212:05raymcdermott@borkdude I'm trying to grok the analysis data#2021-08-2212:05raymcdermottgiven this input#2021-08-2212:06raymcdermott
(ns bar
  (:require [foo :refer [xx]]))

(defn yy [x] (xx x))

(yy 2)
#2021-08-2212:06raymcdermottI get back#2021-08-2212:08raymcdermott
{:namespace-definitions
 [{:filename "<stdin>",
   :row 1,
   :col 1,
   :name bar,
   :name-row 1,
   :name-col 5,
   :name-end-row 1,
   :name-end-col 8}],
 :namespace-usages
 [{:name-end-col 17,
   :name-end-row 2,
   :name-row 2,
   :alias-end-row nil,
   :alias-row nil,
   :filename "<stdin>",
   :from bar,
   :col 14,
   :name-col 14,
   :alias-col nil,
   :alias-end-col nil,
   :row 2,
   :to foo}],
 :var-definitions
 [{:fixed-arities #{1},
   :end-row 4,
   :name-end-col 9,
   :name-end-row 4,
   :name-row 4,
   :ns bar,
   :name yy,
   :defined-by "clojure.core/defn",
   :filename "<stdin>",
   :col 1,
   :name-col 7,
   :end-col 21,
   :row 4}],
 :var-usages
 [{:name-end-col 28,
   :name-end-row 2,
   :name-row 2,
   :name xx,
   :filename "<stdin>",
   :from bar,
   :col 26,
   :name-col 26,
   :row 2,
   :to foo}
  {:name-end-col 17,
   :name-end-row 4,
   :name-row 4,
   :name xx,
   :filename "<stdin>",
   :from bar,
   :col 15,
   :name-col 15,
   :from-var yy,
   :arity 1,
   :row 4,
   :to foo}
  {:name-end-col 6,
   :name-end-row 4,
   :name-row 4,
   :name defn,
   :filename "<stdin>",
   :from bar,
   :macro true,
   :col 2,
   :name-col 2,
   :arity 3,
   :varargs-min-arity 2,
   :row 4,
   :to "clojure.core"}
  {:fixed-arities #{1},
   :name-end-col 4,
   :name-end-row 6,
   :name-row 6,
   :name yy,
   :filename "<stdin>",
   :from bar,
   :col 2,
   :name-col 2,
   :arity 1,
   :row 6,
   :to bar}]}
#2021-08-2212:09raymcdermottI can't trace the definition of xx used in the function yy back to the foo ns#2021-08-2212:14raymcdermottthe :from and :to seem inverted ... but of course I could be reading it wrong 🙂#2021-08-2212:45borkdudeThe usage goes from ns A to the ns B, it just depends on how you look at this#2021-08-2212:46borkdudeThe reference is in ns A (from), the source is in ns B (to)#2021-08-2215:39raymcdermottok, I can get it to work ... I'll hold the telescope the other way 🙂#2021-08-2215:41raymcdermottmy intuition is different - maybe it will change#2021-08-2215:43borkdudeI would say it's better to get over it, it won't change anyway ;)#2021-08-2215:43borkdudelike all bad names in clojure, once they are there, you can't change them#2021-08-2218:36raymcdermottlol I actually meant my intuition rather than the words#2021-08-2218:37borkdudeyes, I understood that#2021-08-2218:38borkdudebut I can now see how that was confusing :)#2021-08-2218:46raymcdermottI appreciate your sympathy!#2021-08-2216:50simonkatzI’ve come across an issue where clj-kondo is mis-reporting the file in which there are problems. There’s a minimal reproduction at https://github.com/simon-katz/bug-report-clj-kondo-misplaced-reports. The README there explains the details. I’m happy to create an issue if that would be useful.#2021-08-2218:32borkdudeThat's a weird bug indeed. Please post an issue and I'll have a look soon#2021-08-2218:52simonkatzOK — that’s done. https://github.com/clj-kondo/clj-kondo/issues/1366#2021-08-2315:24Noah Bogartthis is foolish of me but i’ve forgotten and can’t seem to make it work: how do i disable the :refer :all lint for clojure.test and then stop marking deftest and is as unresolved symbols?#2021-08-2315:27Noah Bogartif it matters, i’m using the #lsp clj-kondo integration instead of relying on clj-kondo directly#2021-08-2315:28Noah Bogartclj-kondo --lint "$(clojure -Spath)" --dependencies --parallel --copy-configs doesn’t make them go away#2021-08-2315:28borkdude@nbtheduke This should work:
(ns foo
  {:clj-kondo/config '{:linters {:refer-all {:exclude [clojure.test]}}}}
  (:require [clojure.test :refer :all]))

(deftest foobar
  (is (= 1 2)))
#2021-08-2315:28borkdudeThere should be no unresolved symbols at all, it works out of the box#2021-08-2315:28borkdudeAt least with clj-kondo + flycheck, no idea about lsp#2021-08-2315:29Noah Bogarti’m not sure what I’m doing wrong, then, thanks#2021-08-2315:29Noah Bogart#2021-08-2315:29borkdudeAre you using any other namespaces with :refer :all?#2021-08-2315:29Noah Bogarti’ll keep poking at it#2021-08-2315:29borkdudeyeah, that should "just work"#2021-08-2315:30borkdudeCan you post this code? I'll try it locally#2021-08-2315:32Noah Bogartthis is a completely fresh, untouched library template from #deps-new, created with clojure -Tnew lib :name io.github.noahtheduke/datalog#2021-08-2315:33Noah Bogarti can open a new github repo with this but i’ve not actually written any code yet lol
#2021-08-2315:33borkdudecan you tell me how to install that tool#2021-08-2315:34Noah Bogart
clojure -Ttools install com.github.seancorfield/deps-new '{:git/tag "v0.1.0" :git/sha "089d868"}' :as new
#2021-08-2315:41borkdude@nbtheduke From a clean slate:
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "15777a677e71607170555857452725242c"}, :content ("[email protected]")}
#2021-08-2315:42borkdudeGoing to try lsp now#2021-08-2315:44borkdudeLooks normal to me:#2021-08-2315:44borkdude(well, I'm using the linting from clj-kondo itself, not lsp)#2021-08-2315:44Noah BogartHmmmmm I don’t know what I broke but I must have broken something. Thanks for verifying. #2021-08-2315:45borkdudePerhaps @ericdallo knows more#2021-08-2315:48borkdudeah yes, I can reproduce when I'm using the lsp linting instead of directly clj-kondo#2021-08-2315:51ericdalloSome users already complained about this, and I never manage to reproduce successfully, not sure if it's something with clj-kondo cache or a source-path wrongly configured 😕#2021-08-2315:51ericdallois there a simple repro?#2021-08-2315:52borkdudeit started working for me when I: 1) created a .lsp folder in the root of the project 2) removed the /tmp/ folder from the workspace (apparently it added that instead of the proper root) 3) deleted .clj-kondo/.cache 4) restarted the workspace 5) imported it from the proper root#2021-08-2315:53ericdallo1. clojure-lsp always create a .lsp folder after a success analyze, no need to create it#2021-08-2315:53borkdudewell, there wasn't one here#2021-08-2315:53borkdudemaybe because there was one in a higher dir?#2021-08-2315:53ericdalloso the project was not analyzed properly by clojure-lsp, the logs or the log to client should say that#2021-08-2315:54ericdalloit depends on what was the project root#2021-08-2315:54ericdallosent by lsp-mode (configured by user)#2021-08-2315:54borkdudeyes, anyway fixing that fixed the problem for me#2021-08-2315:54ericdallocould you confirm your project root is configured properly @nbtheduke?#2021-08-2315:55ericdalloif clojure-lsp doesn't scan the project properly, it will both log to clojure-lsp log and send a message to client which will print something like Classpath lookup failed....#2021-08-2316:02Noah Bogart
"workspaceFolders": [
        {
            "uri": "file:///Users/noah/Personal/datalog/test/noahtheduke",
            "name": "/Users/noah/Personal/datalog/test"
        },
        {
            "uri": "file:///Users/noah/Personal/datalog/src/noahtheduke",
            "name": "/Users/noah/Personal/datalog/src"
        },
        {
            "uri": "file:///Users/noah/Personal/datalog",
            "name": "/Users/noah/Personal"
        },
        {
            "uri": "file:///Users/noah/.vim",
            "name": "/Users/noah"
        }
    ],
#2021-08-2316:02Noah Bogartthat’s what vim sent to clojure-lsp#2021-08-2316:04Noah Bogarthmm, lsp log:
2021-08-23T16:03:49.865Z UnknownHost INFO [clojure-lsp.source-paths:134] - Automatically resolved source-paths from deps.edn: #{"src" "resources" "test"}
2021-08-23T16:03:50.339Z UnknownHost INFO [clojure-lsp.crawler:133] - Analyzing source paths for project root /Users/noah/Personal/datalog
2021-08-23T16:03:50.346Z UnknownHost INFO [clojure-lsp.crawler:77] - Paths analyzed, took 0.006113346 secs. Caching for next startups...
2021-08-23T16:03:50.346Z UnknownHost DEBUG [clojure-lsp.server:?] - :initialize 500ms
2021-08-23T16:03:50.347Z UnknownHost INFO [clojure-lsp.kondo:64] - Linting whole project files took 1ms
2021-08-23T16:03:50.356Z UnknownHost INFO [clojure-lsp.server:350] - Initialized!
2021-08-23T16:03:50.356Z UnknownHost DEBUG [clojure-lsp.server:?] - :initialized 0ms
2021-08-23T16:03:50.361Z UnknownHost DEBUG [clojure-lsp.server:?] - :didOpen 4ms
2021-08-23T16:03:52.362Z UnknownHost DEBUG [clojure-lsp.server:?] - :semanticTokensFull 1ms
2021-08-23T16:03:55.146Z UnknownHost ERROR [clojure-lsp.server:?] -
com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine      PosixJavaThreads.java:  192
            com.oracle.svm.core.thread.JavaThreads.threadStartRoutine           JavaThreads.java:  553
                        java.util.concurrent.ForkJoinWorkerThread.run  ForkJoinWorkerThread.java:  183
                          java.util.concurrent.ForkJoinPool.runWorker          ForkJoinPool.java: 1594
                               java.util.concurrent.ForkJoinPool.scan          ForkJoinPool.java: 1656
             java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec          ForkJoinPool.java: 1020
                             java.util.concurrent.ForkJoinTask.doExec          ForkJoinTask.java:  290
              java.util.concurrent.CompletableFuture$AsyncSupply.exec     CompletableFuture.java: 1692
               java.util.concurrent.CompletableFuture$AsyncSupply.run     CompletableFuture.java: 1700
                  clojure-lsp.server.LSPTextDocumentService/reify/get                 server.clj:  139
                                       clojure-lsp.handlers/did-close               handlers.clj:   69
                        clojure-lsp.feature.file-management/did-close        file_management.clj:  180
                                     clojure-lsp.shared/uri->filename                 shared.clj:  123
                                          clojure.string/starts-with?                 string.clj:  364
java.lang.NullPointerException:

2021-08-23T16:03:55.148Z UnknownHost DEBUG [clojure-lsp.server:?] - :didClose 1ms
2021-08-23T16:03:55.216Z UnknownHost DEBUG [clojure-lsp.server:?] - :didOpen 2ms
2021-08-23T16:03:57.220Z UnknownHost DEBUG [clojure-lsp.server:?] - :semanticTokensFull 0ms
#2021-08-2316:08ericdallosounds like a bug on recent introduced didClose#2021-08-2316:08ericdalloeven so, not related with your issue#2021-08-2316:09Noah Bogartis there another way to determine the project root for lsp?#2021-08-2316:09ericdalloyes, the serverInfo command should return a project-root-uri#2021-08-2316:10ericdalloclojure/serverInfo/log https://clojure-lsp.github.io/clojure-lsp/capabilities/#custom-methods#2021-08-2316:10ericdalloCalva and emacs already have handful commands to get that using that custom method#2021-08-2316:10Noah Bogart:project-root-uri "file:///Users/noah/Personal/datalog"#2021-08-2316:12ericdallois that the correct project root ?#2021-08-2316:12Noah Bogartthat’s where the deps.edn is, yeah.#2021-08-2316:14ericdallocould you try removing both .lsp/sqlite.db and .clj-kondo/.cache?#2021-08-2316:14Noah Bogartyes, one sec#2021-08-2316:15ericdalloit'd be even better if you try one after the other#2021-08-2316:15ericdallotry first clj-kodno/.cache#2021-08-2316:15Noah Bogartoops, did both and it seems to have resolved itself#2021-08-2316:16ericdallonp, is it working properly now?#2021-08-2316:16Noah Bogartyes#2021-08-2316:16Noah Bogartvery strange#2021-08-2316:16ericdallowhat I think it's the issue:#2021-08-2316:21ericdalloclojure-lsp call clj-kondo 3 (independent from errors) times: 1. during init, after get the project classpath, to get external analysis (jars), calling clj-kondo passing the whole classpath (excluding project source-paths) 2. during init, after 1., to analyze only project source-paths 3. after any file change, running for a single file, but not important for this isue What I suspect is that, 1. doesn't run properly, but 2. runs fine, persisting a .clj-kondo/cache with only cache for project, not containing external deps#2021-08-2316:21ericdalloWDYT @U04V15CAJ?#2021-08-2316:24borkdudewell, if you have only 2, then the above issue shouldn't have happened, since clj-kondo already has a built-in cache for clojure.test#2021-08-2316:25borkdudebut if 1 lints clojure.test not correctly then there will be some invalid cache analysis fo clojure.test, which is more likely to cause the issue#2021-08-2316:27ericdalloyeah, I think it's related with old cache or something like that if you manage to repro again, let us know @nbtheduke#2021-08-2316:28borkdudeit would have been interesting indeed to inspect the contents of .clj-kondo/.cache after this happened#2021-08-2317:48Noah BogartI’ll keep an eye out and if I see it again, I’ll post it! #2021-08-2317:49ericdalloThanks, it's something that happens from time to time, the first report I saw of this was on Calva back on Feb/2020! So it'd be really nice if we manage to fix it somehow#2021-08-2315:53borkdude^ @nbtheduke FWIW#2021-08-2420:08borkdude@deleted-user linting for compojure is built into clj-kondo :)#2021-08-2420:08borkdudeso if your macro is syntactically the same you could use :lint-as#2021-08-2502:42mafcocincoIs there a place to track enhancement requests for clj-kondo? I noticed that clj-kondo stops warning about a private function which is not used if that function is overloaded.#2021-08-2502:42mafcocincoWould be nice to not only retain the warning but perhaps highlight the specific functions which are not called.#2021-08-2502:50seancorfield@mafcocinco Do you mean, e.g., warning about the 2-arity not being used if there's a 1-arity version and it is used?#2021-08-2502:50seancorfield(trying to figure out what you mean by "overloaded")#2021-08-2502:51seancorfieldAs for issues/discussions: https://github.com/clj-kondo/clj-kondo#2021-08-2502:51mafcocincoyes, overloaded on arity. And yes to your first comment, though it seems like it also a bug as the warning never shows up for any arity.#2021-08-2502:51seancorfieldInteresting. I hadn't noticed that. I'll keep an eye out for that.#2021-08-2502:52Joshua SuskaloThat might be a little hard to track effectively since apply exists.#2021-08-2502:53Joshua SuskaloThat is, you can't just track places the symbol is used anymore if you want to track which arity is being used.#2021-08-2502:55Joshua Suskalo
(defn some-func
  ([a] [a])
  ([a b] [a b]))

(map some-func data-1 data-2)
In order for this to know that the 2-arity is being used but not the 1-arity, it has to know what map does, which means we have to have special casing or do much more advanced static analysis. Special casing breaks down on user-defined functions, and advanced static analysis is probably outside the scope of clj-kondo.
#2021-08-2502:57Joshua SuskaloThe only relatively easy way to solve this issue as far as I can tell would be to only use this linter if the only place the var is used is directly as a function call with a fixed number of arguments, but then the linter isn't very useful imo.#2021-08-2502:58Joshua SuskaloBut whether or not that use is enough to warrant the implementation is up to the people who would implement it I guess.#2021-08-2503:04seancorfieldGood points, yeah.#2021-08-2513:25Jakub Holý (HolyJak)Hello! Do I need to do something special to enable Schema support in kondo? Currently it complains about "Unresolved symbol: User" here:
(require '[my.schemas :refer [User]] '[schema.core :as s])
(s/defn admin-user?
  [user :- User]
  ...)
Update: This is weird, running clj-kondo manually works just fine. The error is shown in Cursive via LSP
#2021-08-2513:27borkdudeSchema support is built into clj-kondo. Your example works in my emacs + vanilla clj-kondo: Are you perhaps using clojure-lsp?#2021-08-2513:28Jakub Holý (HolyJak)exactly, clojure-lsp in Cursive#2021-08-2513:28borkdudeinteresting. are you sure the warning in your case is coming from clj-kondo?#2021-08-2513:29borkdudeand not from cursive for example#2021-08-2513:31Jakub Holý (HolyJak)https://www.dropbox.com/s/bgu9eglc8vezvnz/Screenshot%202021-08-25%20at%2015.30.53.png?dl=0 - it seems coming from LSP server#2021-08-2513:33borkdudeVery interesting. Could you make a zip of .clj-kondo/.cache and send it to me, if it doesn't contain any sensitive info? @UKFSJSM38 and me are trying to solve this issue for some time now#2021-08-2513:34borkdudeThe workaround is to remove .clj-kondo/.cache and .lsp/sqlite.db and then restart your workspace, but we would love to have some data to debug#2021-08-2513:36ericdalloIs that the same issue of cache removals? The User seems to be a schema from the project itself, not external deps#2021-08-2513:36ericdalloanyway, a zip would help confirm it indeed 🙂#2021-08-2513:37borkdudeyes, it would help if the screenshot also showed where User is coming from#2021-08-2513:37borkdudemore details = more better...#2021-08-2513:40borkdudebtw, it's interesting you're using Cursive. I think it would be useful to have some docs around how to use clojure-lsp in cursive#2021-08-2513:40ericdalloYeah, actually I didn't know both would work fine together :thinking_face:#2021-08-2514:07Jakub Holý (HolyJak)I will send the zip later today. Do y have Keybase or what do you prefer? The schema is defined in another ns and required with :refer :all#2021-08-2514:10Jakub Holý (HolyJak)But how goes kondo cache help? I've run kondo from CLI and that was just fine, I assume it used the cache. Since the problem only appears in kondo via lsp, you perhaps need (also).lsp (or, in the case of IntelliJ, there is also lsp (without dot))#2021-08-2514:12ericdallo.lsp/sqlite.db is the folder used by clojure-lsp just for caching external analysis, when we remove it, clojure-lsp re scan the whole classpath again using clj-kondo (which should cache that on .clj-kondo/.cache as well)#2021-08-2514:42borkdude@U0522TWDA the command line version only uses the cache created by the editor if both clj-kondo versions are exactly the same#2021-08-2514:43ericdallogood point, probably your clj-kondo cli version is different from the one used by clojure-lsp#2021-08-2514:55Jakub Holý (HolyJak)No, both versions are the same#2021-08-2514:56borkdudeyou can check is to see if there is only one recent .clj-kondo/.cache/* dir in there#2021-08-2514:56borkdudeand not two different ones, I mean inside the .cache dir#2021-08-2515:16Jakub Holý (HolyJak)Sorry 😢 I have restarted LSP from Cursive and it does not show the error anymore.#2021-08-2515:17Jakub Holý (HolyJak)Good news! I deleted kondo cache and restarted LSP and re-opened the file and see the error again#2021-08-2515:18Jakub Holý (HolyJak)interestingly, I do NOT have .clj-kondo/.cache/ in the project dir now#2021-08-2515:18Jakub Holý (HolyJak)the only relevant thing I seem to have is ./lsp/#2021-08-2515:19borkduderestart cursive itself perhaps#2021-08-2515:19borkdudehuh#2021-08-2515:20borkdudenow I'm really confused ;)#2021-08-2515:20ericdallohum, even if your classpath is cached on .lsp/sqlite.db , clojure-lsp calls clj-kondo to lint the project paths at every startup, then it should create a .clj-kondo/.cache (only if you have a .clj-kondo folder)#2021-08-2515:20Jakub Holý (HolyJak)Me too. Now the problem is there even in CLI:
❯ java -jar ~/Downloads/clj-kondo-2021.08.06-standalone.jar --lint src/mine/core.clj
src/mine/core.clj:4:35: warning: use alias or :refer
src/mine/core.clj:38:12: error: Unresolved symbol: User
#2021-08-2515:20ericdallowhat makes sense because there is no cache, right @U04V15CAJ?#2021-08-2515:21borkdude@U0522TWDA Please provide more details. The complete source.#2021-08-2515:22borkdudeit looks like you're using :refer :all or something (from the linter warning I can see that)#2021-08-2515:22borkdudeand that's expected not work with without a cache#2021-08-2515:22Jakub Holý (HolyJak)Correct, the .clj-kondo/ dir that I deleted recently has not been recreated by running the CLI. @U04V15CAJ I'd love to but it is company property so I cannot really share more than snippets 😿#2021-08-2515:22Jakub Holý (HolyJak)Yes, I am using refer all, I think I mentioned it above#2021-08-2515:23borkdudeyou need to make LSP re-index your project#2021-08-2515:23ericdallo@U0522TWDA probably you will be able to repro if create a new sample project with schema.core dep?#2021-08-2515:23borkdudedon't know how to do that in Cursive#2021-08-2515:23Jakub Holý (HolyJak)
(ns
  (:require [company.schemas :refer :all] ; User lives here
            [schema.core :as s]))
(s/defn backoffice-user?
  [user :- User]
  ...)
#2021-08-2515:23ericdallo> you need to make LSP re-index your project for clojure-lsp, removing .lsp/sqlite.db or changing anything in your project.clj/deps.edn should work#2021-08-2515:24Jakub Holý (HolyJak)ok, will try to make a repro repo later today. Thank you for all the support!#2021-08-2517:02Jakub Holý (HolyJak)Ok, so if I have (:require [kondo-lsp-cursive-schema-problem.core :refer [User]]) then kondo is happy but if I change it to ...:refer :all then it says "Unresolved symbol: User" @U04V15CAJ do you want a .tbz of the whole project repo or is this a known problem?#2021-08-2517:03ericdalloa public repo on Github would be the best, otherwise a zip/tar.gz is enough as well#2021-08-2517:20borkdude@U0522TWDA That example is expected to work like that, if you don't have a .clj-kondo/.cache with the namespace kondo-lsp-cursive-schema-problem.core linted#2021-08-2517:21borkdudebut if you do have .clj-kondo/.cache dir and then you lint that namespace, after that, it should work#2021-08-2517:21Jakub Holý (HolyJak)Ah, I expected that if I open a new project, LSP would index it automatically. Obviously it did not#2021-08-2517:21borkdudeso lint the other namespac#2021-08-2517:21borkdudeyes, I would expect that too, but I'm not sure why it doesn't#2021-08-2517:22Jakub Holý (HolyJak)How do I get LSP to index anything? I changed a comment in project.clj but still not .clj-kondo ...#2021-08-2517:23borkdudeyou must create the .clj-kondo dir yourself#2021-08-2517:23borkdudeonly remove the .cache dir from it, not the dir itself#2021-08-2517:23borkdudeyou're expected to host some configuration in that directory#2021-08-2517:23borkdude.clj-kondo/config.edn#2021-08-2517:24borkdudeand when you have a .clj-kondo dir, only then will clj-kondo store cache info there#2021-08-2517:24ericdalloI wonder if clojure-lsp should always create the .clj-kondo dir in the project. what do you think @U04V15CAJ?#2021-08-2517:24borkdudeyes, I'm fine with that#2021-08-2517:24ericdallootherwise projects without that folder always will have that issue#2021-08-2517:24borkdudejust at the same position as .lsp#2021-08-2517:25borkdudeperhaps also put a config.edn there automatically with just an empty map#2021-08-2517:25borkdudeif it doesn't exist#2021-08-2517:25Jakub Holý (HolyJak)https://github.com/holyjak/tmp-kondo-lsp-cursive-schema-problem#2021-08-2517:32ericdallo> perhaps also put a `config.edn` there automatically with just an empty map I suppose people would think that .clj-kondo/config.edn should not be commited if we do that automatically 😕#2021-08-2517:32ericdallo@U0522TWDA I'll try to repro with clojure-lsp later today, thanks#2021-08-2517:32Jakub Holý (HolyJak)Added the config there , cache created, problem persists. Both ns are indexed: kondo-lsp-cursive-schema-problem.core.transit.json kondo-lsp-cursive-schema-problem.schemas.transit.json#2021-08-2517:34borkdude@U0522TWDA I don't think this repro makes sense. You are referring the same namespace with :refer :all from the namespace itself#2021-08-2517:35borkdude
(ns kondo-lsp-cursive-schema-problem.core
  (:require
    ;[kondo-lsp-cursive-schema-problem.core :refer [User]]
    [kondo-lsp-cursive-schema-problem.core :refer :all]
    [schema.core :as s]))
#2021-08-2517:35Jakub Holý (HolyJak)> I suppose people would think that `.clj-kondo/config.edn` should not be commited if we do that automatically That is much less of a risk/inconvenience than the current state when linting does not work fully out of the box. (Of course we can blame the user - me - for not reading kondo docs and expecting stuff to just magically do what I want :))#2021-08-2517:35Jakub Holý (HolyJak)OMG, sorry, typo#2021-08-2517:35borkdudeWhen I change it to [kondo-lsp-cursive-schema-problem.schemas :refer :all] then it works for me#2021-08-2517:35Jakub Holý (HolyJak)Right, when I fix the require, it works at once#2021-08-2517:36ericdallo> That is much less of a risk/inconvenience than the current state when linting does not work fully out of the box. (Of course we can blame the user - me - for not reading kondo docs and expecting stuff to just magically do what I want :)) But not creating that would not cause the issue, it was just a suggestion, the issue here is the .clj-kondo folder creation#2021-08-2517:37ericdalloso, in the end the issue was the .clj-kondo folder that didn't exists, right?#2021-08-2517:37borkdudeI think so#2021-08-2517:37borkdudeI think creating the config.edn is a nice addition: it suggests where people should store their config#2021-08-2517:38borkdudeperhaps with links to the config page :)#2021-08-2517:38borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#2021-08-2517:38Jakub Holý (HolyJak)In the repro, yes. At work it did/does exist. But when I open it, the cache has only files for very few namespaces, not including the .schemas one. Why could that be?#2021-08-2517:39ericdallo> I think creating the config.edn is a nice addition: it suggests where people should store their config we can do that I think, and re-think if anyone complains#2021-08-2517:39ericdallo> Why could that be? Probably removing both .lsp/sqlite.db and .clj-kondo/.cache would solve#2021-08-2517:39Jakub Holý (HolyJak)No, sorry, missed it, .schemas as well as .core are there#2021-08-2517:40borkdudeperhaps the indexing broke off with an error?#2021-08-2517:41ericdalloanything on clojure-lsp server log? https://clojure-lsp.github.io/clojure-lsp/troubleshooting/#server-log#2021-08-2517:41borkdudeI do see this:
$ ls .clj-kondo/.cache/2021.08.07-SNAPSHOT/clj
kondo-lsp-cursive-schema-problem.core.transit.json    kondo-lsp-cursive-schema-problem.schemas.transit.json
which is what I would expect
#2021-08-2517:41borkdudewell I would also expect some for clojure itself and schema#2021-08-2517:41borkdudeso it seems it didn't index deps#2021-08-2517:42ericdalloI think what happened was:#2021-08-2517:42borkdudeoh wait, I have 2 cache dirs:
$ ls .clj-kondo/.cache/2021.07.28/
clj  cljc cljs lock
#2021-08-2517:42borkdudeso that's the one with all the deps#2021-08-2517:42borkdudebut this is using an older clj-kondo it seems#2021-08-2517:43borkdude` $ clojure-lsp --version clojure-lsp 2021.07.28-14.24.06 clj-kondo 2021.07.28 #2021-08-2517:43borkdudeah, that makes sense#2021-08-2517:43Jakub Holý (HolyJak)the .schemas transit file does contain the User (thanks, jet !)#2021-08-2517:43ericdallothere was no .clj-kondo dir, clojure-lsp called clj-kondo that linted classpath and lsp saved .lsp/sqlite.db , but nothing saved on .clj-kondo/.cache as the did was not there. After creating the .clj-kondo folder we need to re-scan the classpath to fulfill the clj-kondo cache folder, that's why removing .lsp/sqlite.db should fixes it, WDYT?#2021-08-2517:44borkdudeyeah. always ensuring a .clj-kondo dir would fix that problem as well#2021-08-2517:44ericdalloexactly#2021-08-2517:44ericdallomaybe that would solve a lot of headache#2021-08-2517:45borkdudeI can see one edge case with this#2021-08-2517:45borkdudewhat if people have a mono-repo and only one .clj-kondo dir at the top level#2021-08-2517:45borkdudeand a shared config for all projects inside the mono repo#2021-08-2517:45borkdudeI don't know if this happens a lot#2021-08-2517:46Jakub Holý (HolyJak)not sure where the sqlite is in Cursive+LSP, I have no .lsp, only lsp/ that contains log/ and conf/clojure.json#2021-08-2517:46borkdudethat lsp folder is created by the IntelliJ LSP plugin#2021-08-2517:47ericdalloyeah, ATM it's suggested that you use clojure-lsp at the mono root, not sure if clj-kondo caches would conflict from subproject to subproject though#2021-08-2517:47borkdudeThe .lsp folder is created by clojure-lsp though. Perhaps it should be called .clojure-lsp? ;)#2021-08-2517:47borkdudeok, let's ignore the mono-repo situation for now, I'm not using that myself in that way, perhaps an edge case to consider later#2021-08-2517:47ericdallo> The .lsp folder is created by clojure-lsp though. Perhaps it should be called .clojure-lsp? 😉 Yeah, there is a issue about that, we would need avoid the breaking changes, but it'd be the ideal indeed#2021-08-2517:48Jakub Holý (HolyJak)Any idea why I do not have that repo created? Is it because the IntelliJ LSP plugin runs clojure-lsp in some other dir or something?#2021-08-2517:50borkdudeperhaps the lsp/logs tells something about whether / how its doing stuff?#2021-08-2517:50ericdalloFYI: https://github.com/clojure-lsp/clojure-lsp/issues/528#2021-08-2517:51ericdallo@U0522TWDA follow the https://clojure-lsp.github.io/clojure-lsp/troubleshooting/section, the server logs should help#2021-08-2517:51Jakub Holý (HolyJak)both lsp/log/clojure_out_20210825.log and _err_ are empty though#2021-08-2517:52ericdalloI don't think both logs are related with clojure-lsp:https://clojure-lsp.github.io/clojure-lsp/troubleshooting/#server-log#2021-08-2517:56Jakub Holý (HolyJak)according to https://github.com/gtache/intellij-lsp#faq those files have, I assume, stdout and stderr from clojure-lsp. I will study clojure-lsp docs to figure out where its actual logs are.#2021-08-2517:58ericdalloI think the _err_ is the stderr from the clojure-lsp process, which unless a huge bug prints to that#2021-08-2517:59ericdallowhat we want is the custom log from the server, which the plugin (since it's a generic intellij LSP plugin) doesn't know about it, unless the plugin explicitly integrates with, which is what Calva does#2021-08-2518:19Jakub Holý (HolyJak)hm, the newest log I found was <.tmpdir>/clojure-lsp.11604520859388497386.out which is from yesterday and has last log from 2021-08-24T13:01:27.545Z#2021-08-2518:20ericdalloyou can easily add {:log-path "/tmp/clojure-lsp.out"} in your .lsp/sqlite.db , this will help get the log from the sample place#2021-08-2518:23Jakub Holý (HolyJak)Will do. I have killed the processes and a new clj-kondo-lsp-server-standalone.jar was started but no new logfile#2021-08-2518:26Jakub Holý (HolyJak)Hm, I've created
❯ cat .lsp/config.edn                                                                                                  
{ :log-path "/tmp/clojure-lsp-myapi.out"}
in the [project dir and LSP plugin - restart server, which started a new kondo-lsp-server process, but the log file did not get created (and there is no sqlite.db in the freshly created .lsp dir)
#2021-08-2518:27ericdalloCan you use a different folder than tmp? (that's why it's not the default to use tmp, but java tmp folder, for persmisions issues, specially on macos)#2021-08-2518:29Jakub Holý (HolyJak)I have done that now and restarted, still no log#2021-08-2518:31Jakub Holý (HolyJak)Interesting, According to Activity Monitor's Open Files, it does not have any log file open. Also, its CWD is wrong (I have 4 projects open in IntelliJ and it is one of them but not the one which I am actively using now)#2021-08-2518:32ericdalloare you really using clojure-lsp? Can you check if there is a clojure-lsp process running?#2021-08-2518:33Jakub Holý (HolyJak)No, it is not, only clj-kondo-lsp-server-standalone.jar Does it not include clojure-lsp?#2021-08-2518:34Jakub Holý (HolyJak)I followed these instructions https://github.com/clj-kondo/clj-kondo/blob/master/doc/editor-integration.md#lsp-server-1#2021-08-2518:36ericdallooh, you are using the clj-kondo LSP project, not clojure-lsp 😅#2021-08-2518:36ericdalloYou are using https://github.com/clj-kondo/clj-kondo.lsp, not https://clojure-lsp.github.io/clojure-lsp/#2021-08-2518:37Jakub Holý (HolyJak)I am sorry, I am new to all this and do not distinguish properly between what is what 🤯#2021-08-2518:37ericdallothey both are LSP servers for clojure and both use clj-kondo, but they do things different#2021-08-2518:38ericdalloeven so, it seems that the clj-kondo.lsp has the cache issue as well @U04V15CAJ 😂#2021-08-2518:41Jakub Holý (HolyJak)I see now. Which one of the two should I use? I picked the one b/c that is what clj-kondo pointed me to...#2021-08-2518:42ericdalloI think clojure-lsp is the closest to Cursive, I'd suggest giving it a try https://clojure-lsp.github.io/clojure-lsp/installation/#2021-08-2518:42borkdudeAaaaah :)#2021-08-2518:43borkdudeYeah, clj-kondo lsp is not clojure-lsp :)#2021-08-2518:43borkdudeI can see how that is confusing :)#2021-08-2518:43borkdudethe clj-kondo lsp doesn't index your project at all#2021-08-2518:43borkdudeyou still have to do it manually, clj-kondo is very lazy#2021-08-2518:43borkdudebut clojure-lsp is pro-active 💪#2021-08-2608:03Jakub Holý (HolyJak)Ok, thx! Then I will switch to clojure-lsp and see how that works. Still, I do not understand why it fails to resolve User in my case because I see the transit file for the schemas ns, which I would believe means that kondo has indexed it. Or?#2021-08-2608:04borkdudeIt indexes it if you lint it manually on the command line in the presence of a .clj-kondo directory, or if you edit the file in your editor and it gets linted then (also in the presence of a .clj-kondo dir)#2021-08-2608:05borkdudeAnd then it should indeed work. Your repro did work for me.#2021-08-2608:08Jakub Holý (HolyJak)Ah, somehow it works here now as well. I guess it was some timing issue, with kondo's updated info not being propagated all the way via LSP to Cursive.#2021-08-2513:29borkdude@mafcocinco @seancorfield about the private self-referring var that is not considered being unused: this warrants an issue I think, please make one#2021-08-2513:42mafcocincoI think I figured out what is going on. Not sure if it is exactly a bug, but seems like it should be. Posting code in a moment#2021-08-2513:45mafcocinco#2021-08-2513:46borkdudeyes, that's what I mean, I think self-references should not count as usages for the unused private var linter#2021-08-2513:46mafcocincoGiven that using one arity of a multi-arity function as an implementation of another is as fairly common pattern, perhaps clj-kondo should ignore the internal usages within the definition of the function?#2021-08-2513:47mafcocincoI will add an issue.#2021-08-2513:52mafcocincoseems like this should apply for all functions, not just private ones, no?#2021-08-2513:52mafcocinconvm, I suppose you don’t get the warning for public functions. 🐶#2021-08-2513:54borkdudewell, clojure-lsp does that but perhaps @UKFSJSM38 already took that into account#2021-08-2513:57ericdalloyeah, that's something to improve/fix on both unused-private-var and clojure-lsp/unused-public-var linters IMO, they consider the function internal usage#2021-08-2513:57borkdudeok, I'll first improve the private one and perhaps the same logic can be applied to the public one. perhaps by adding a :self-ref true or so on the usage#2021-08-2513:58ericdalloLooks good!#2021-08-2513:59ericdalloLSP code lens are affected by that as well#2021-08-2514:00ericdalloI just wonder if we should just fix the lint, but references and code lenses should still show those usages#2021-08-2514:02mafcocincohttps://github.com/clj-kondo/clj-kondo/issues/1367#2021-08-2609:35borkdudeFixed on master.#2021-08-2513:38Karol WójcikDoes anybody have the valid hook for shadow.markup.css/defstyled macro? 😄 Example:
(css/defstyled Container :div
  [env]
  {:position "absolute"
   :bottom "24px"
   :right "24px"})
#2021-08-2513:39borkdudeProbably {:lint-as {... clj-kondo.lint-as/def-catch-all}} works here#2021-08-2513:42Karol WójcikYep! It works! Thanks @U04V15CAJ ❤️#2021-08-2616:43richiardiandreaHi everybody, this might have been asked already, but why is this a linting error (using specter ). Did anybody run into this already?#2021-08-2616:44Joshua SuskaloWhat's the warning?#2021-08-2616:44Joshua SuskaloI might've just missed a couple things in my specter config that I added to the readme.#2021-08-2616:46richiardiandreait's unresolved symbol#2021-08-2616:46Joshua Suskaloalright, I'll take a look at it#2021-08-2616:46Joshua SuskaloDo you have the config from specter's readme already in your project?#2021-08-2616:48richiardiandreanot yet, let me check that#2021-08-2616:48richiardiandrea@U5NCUG8NR is it the clj-kondo readme?#2021-08-2616:49Joshua SuskaloNo, it's in the specter readme. https://github.com/redplanetlabs/specter#clj-kondo#2021-08-2616:49richiardiandreaOh cool, no I definitely haven't seen that#2021-08-2616:49Joshua SuskaloYeah, that will fix a lot (if not all) of your unresolved symbol errors.#2021-08-2616:53richiardiandreauhm it seems like they are still there#2021-08-2616:54richiardiandreawait, blowing the cache might have solved it#2021-08-2617:03Joshua SuskaloYeah, you have to blow the cache and run clj-kondo --dependencies --lint "$(clojure -Spath)" when you do stuff like this.#2021-08-2617:34borkdudeIt would be cool if specter could include this in its lib, but I guess README would do#2021-08-2617:35richiardiandreayeah I was thinking the same#2021-08-2617:35Joshua SuskaloYeah I asked nathan and the preference was to not include it in the artifact since not everyone uses kondo and it would increase the artifact size, even if only slightly.#2021-08-2617:35Joshua SuskaloI would be happy to PR this into the clj-kondo/config repo though.#2021-08-2617:35richiardiandrea@U5NCUG8NR I think we also have some instances of sp/richnav like:
(def ^:private terminal2
  (sp/richnav [afn]
              (sp/select* [_this _vals _structure _next-fn]
                          (throw (Exception. "'terminal2' should only be used in multi-transform")))
              (sp/transform* [_this vals structure _next-fn] (afn vals structure))))
#2021-08-2617:36borkdudeyearh clj-kondo/config would be ok too. I think Nathan wasn't using clj-kondo at the time, but now he is, so perhaps his opinion has changed#2021-08-2617:36borkdudebut clj-kondo/config is always an option#2021-08-2617:39Joshua SuskaloI could run it by him again at some point.#2021-08-2617:40Joshua SuskaloAlso @U0C8489U6 that's kinda out of scope for the minor config that I was making. That config is just meant to allow you to use all the vars from inside specter without them showing up as undefined. It's not meant to give you reasonable semantics for writing your own navs.#2021-08-2617:40richiardiandreaok sounds good#2021-08-2617:40richiardiandreaI think I will just disable linting for that then for now#2021-08-2617:40Joshua SuskaloAlthough if nathan is interested in adding clj-kondo support to specter, I could consider writing hooks for the macros which would support custom navigators past not showing up as undeclared.#2021-08-2617:41Joshua SuskaloWhich even if he isn't interested, that'd be a significant effort, so I'd want to at least pull it on clj-kondo/config#2021-08-2619:32richiardiandreaThank you for your work on that Joshua, it really helped here#2021-08-2817:31Darin Douglassany idea why kondo sees env as an unused binding? example2 is the work-around i found for the issue. both fns work as expected. i'm running the most recent version
➜ clj-kondo --version
clj-kondo v2021.08.06
#2021-08-2817:32borkdudethat must be a bug in the linting for that macro. please submit an issue#2021-08-2817:32borkdudeand provide the code as text so it's easy for me to make a test case#2021-08-2817:32Darin Douglasswill do!#2021-08-2817:33Darin Douglassi figure on babashka.process is the right spot for that ticket?#2021-08-2817:34borkdudeactually clj-kondo#2021-08-2817:34borkdudethis is built into it#2021-08-2817:35Darin Douglassah, i saw the hooks kondo config in the process repo#2021-08-2817:35borkdudeah that's no longer used, I should probably remove it#2021-08-2817:35borkdudeplease mention that in the issue as well#2021-08-2817:36Darin Douglass+1#2021-08-2817:42Darin Douglasshttps://github.com/clj-kondo/clj-kondo/issues/1368#2021-08-2817:44borkdudethanks#2021-08-2817:49Darin Douglassthank you!#2021-08-3013:12Jakub Holý (HolyJak)Hi! Any idea why running
clj-kondo --copy-configs --dependencies --lint (clojure -Spath)
inside https://github.com/holyjak/minimalist-fulcro-template-backendless does not offer to import clj-config exports from Fulcro? The deps have the latest Fulcro with kondo exports https://github.com/fulcrologic/fulcro/tree/c840483be0c635825b47b8f6434c98de093bf83c/resources/clj-kondo.exports/com.fulcrologic/fulcro 🙏
#2021-08-3013:13borkdudeyou need a dollar sign before (clojure -Spath)#2021-08-3013:15borkdude^ @holyjak#2021-08-3013:17Jakub Holý (HolyJak)not really, I run this in Fish not bash. The command is working for Pathom. Sorry for not proiding that info up front!#2021-08-3013:17borkdudethen it's probably because fulcro doesn't have resources on its classpath: https://github.com/fulcrologic/fulcro/blob/c840483be0c635825b47b8f6434c98de093bf83c/deps.edn#L1#2021-08-3013:18borkdudeso the clj-kondo stuff isn't actually inside the jar#2021-08-3013:18borkdudeor git lib#2021-08-3013:19Jakub Holý (HolyJak)Ah, ok, many thanks!#2021-08-3013:19borkdudeMy pleasure :)#2021-08-3117:26Noah Bogartis it possible to exclude a given symbol’s use?#2021-08-3117:26Noah Bogartsomething like {:disallowed [clojure.core/cond]}#2021-08-3117:26Noah Bogartand then if that symbol is used, a warning/error is thrown#2021-08-3117:33borkdudeThere is an open issue about this: https://github.com/clj-kondo/clj-kondo/issues/996 Feel free to provide feedback or upvote it using a thumbs up#2021-08-3117:34borkdudeYou can also leverage the analysis output to look for used vars and do your own thing with it, currently#2021-08-3117:41Joshua SuskaloInteresting concept, but I gotta ask, of all the vars you could disallow, cond?#2021-08-3117:50Noah Bogartwell, 1) it’s just an example, but 2) i adapted Racket’s cond and want to use it in my library and want to enforce using it instead of the built-in cuz i am the literal devil#2021-08-3118:58Joshua Suskalolol#2021-08-3117:51Noah Bogartvery cool, thank you. i’ve subscribed to that issue, don’t have much to add yet tho#2021-08-3118:22Noah Bogartjust wrote my first hook! Very nifty and easy to use.#2021-08-3119:04Noah BogartTo double check, if I want to export a library’s config and hooks, this should be the folder structure? (output from git status)
new file:   .clj-kondo/config.edn
	new file:   .clj-kondo/hooks/cond_plus.clj
	new file:   resources/clj-kondo.exports/cond-plus/cond-plus/config.edn
	new file:   resources/clj-kondo.exports/cond-plus/cond-plus/hooks/cond_plus.clj
#2021-08-3119:58borkdude@nbtheduke Yes. You can even add resources/clj-kondo.exports/cond-plus/cond-plus to :config-paths into your .clj-kondo/config.edn so you don't have to duplicate your config#2021-08-3120:15Noah BogartI’m struggling to get this to work#2021-08-3120:16Noah Bogart
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "ea84858b82aaa4858b8299c7a7a8ba"}, :content ("[email protected]")}
#2021-08-3120:17Noah Bogarti’ve modified the test file to produce an error, which should be caught by kondo, and instead it’s telling me about something that should be ignored#2021-08-3120:18Noah Bogart
$ head resources/clj-kondo.exports/cond_plus/cond_plus/cond_plus/cond_plus.clj
(ns cond-plus.cond-plus
  (:require [clj-kondo.hooks-api :as api]))

(defn analyze-clauses [clauses]
  (reduce
    (fn [found-else? clause]
      ;; non-sequence clause
      (if (not (or (api/list-node? clause)
                   (api/vector-node? clause)))
        (let [{:keys [row col]} (meta clause)]
#2021-08-3120:19Noah Bogart(lol at cond_plus/cond_plus/cond_plus/cond_plus.clj)#2021-08-3120:19borkdude:)#2021-08-3120:19borkdudeit's similar to the layout in a mvn dir#2021-08-3120:20borkdudeI'll take a look in a bit
#2021-08-3120:20Noah Bogartno worries#2021-08-3121:09Noah Bogartdid some digging and it seems that the :config-paths is relative from the config.edn file, not from the project root/where clj-kondo is called?#2021-08-3121:09borkdudecorrect#2021-08-3121:09Noah Bogartokay, seems i misunderstood that#2021-08-3121:10borkdudeI might have overlooked that as wel#2021-08-3121:10borkdudeso then it would be config-paths ["../resources/etc"]#2021-08-3121:11Noah Bogartyep! doing that makes it work#2021-08-3121:12borkdudegreat! @U0522TWDA this is what I tried to explain yesterday with the fulcro lib#2021-08-3119:58borkdude@nbtheduke Also note that you have to lowercase your directory names: cond_plus/cond_plus#2021-08-3119:58borkdudeand I would advise to use an org name like noah_the_duke/cond_plus instead#2021-08-3119:58borkdudeto not conflict with other configs for the same macro#2021-08-3120:01Noah Bogarti suspect this is outside the scope of this channel, but i’ve already published the library with that org, so i’m not sure how I would go about changing it#2021-08-3120:01Noah Bogarti’ll keep that in mind in the future#2021-08-3120:02borkdudeI would recommend changing it for the next release#2021-08-3120:02borkdudeor is the library's name cond-plus? then it may not be that bad#2021-08-3120:03borkdudeperhaps a link to the lib?#2021-08-3120:03Noah Bogarthttps://clojars.org/cond-plus#2021-08-3120:04borkdudeok yeah that makes sense, thanks#2021-08-3120:05borkdudeI didn't mean changing the org for your lib but for the clj-kondo exports#2021-08-3120:05borkdudebut now I see that's actually what the lib is published like, so all good#2021-08-3120:05borkdudeas long as conflicts are avoided then it's ok basically#2021-08-3120:07borkdudeso instead of hooks/cond_plus.clj it would be actually better to choose cond_plus/cond_plus.clj as well, since there may be someone else who has a hooks/cond_plus.clj file in their config and then they will conflict#2021-08-3120:08borkdudebasically the same as with clojure code and classpaths#2021-09-0217:47Joshua SuskaloContinuing from #tools-deps, where should I look to see about integrating with clj-kondo's analysis to get information out of vars?#2021-09-0217:48Joshua Suskalo@borkdude#2021-09-0217:49borkdude@suskeyhose Let me get back to you on that in 15 minutes or so#2021-09-0217:49Joshua Suskalocool#2021-09-0217:50Joshua Suskalono rush#2021-09-0217:51Joshua SuskaloSo I'm taking a peek at the analysis folder and it looks like only specific metadata is exported, and for my usecase I'd need the :style/indent metadata to be exported as well. Possibly a very small change. In any case I need to keep reading.#2021-09-0218:08borkdude@suskeyhose This is correct. But! There is an issue to collect arbitrary metadata and the fix for this is pretty easy, so perhaps you could provide some input and we can finally implement this. https://github.com/clj-kondo/clj-kondo/issues/1280#2021-09-0218:09borkdudeI would be ok with just adding all metadata on a :meta key or so, when providing an option. The only "danger" is that metadata contains stuff that isn't readable as EDN or so.#2021-09-0218:10Joshua SuskaloAh, I see, since the data is passed over stdout it could cause issues.#2021-09-0218:10borkdudewell, clj-kondo is also available as a JVM library#2021-09-0218:10Joshua SuskaloRight, that's what I'd want to use it as.#2021-09-0218:10borkdudebut it'd be nice if we supported both use cases at once: the EDN output should preferably be valid.#2021-09-0218:11borkdudeAnd the most secure way to do that is to just provide values as strings perhaps#2021-09-0218:11borkdudeusing pr-str#2021-09-0218:12borkdudeOR we could make the selection of metadata optional (like in the issue) and then any EDN errors are the problem of the caller.#2021-09-0218:12borkdudeor we could choose to only export metadata with keywords as keys and constants as values#2021-09-0218:13Joshua SuskaloI think having the :var-meta key like in the config is valid, and make it so just having true for it will return everything.#2021-09-0218:13borkdudeNote that this is valid: ^{(+ 1 2 3) (+ 4 5 6)}#2021-09-0218:14Joshua SuskaloHmm.#2021-09-0218:14borkdudethat's what I'm thinking of#2021-09-0218:14Joshua SuskaloI see.#2021-09-0218:14borkdudethose cases are rare, but they do exist#2021-09-0218:14borkdudeso if the metadata has ^{:foo "bar"} then we'd export :foo "bar" but when it's :foo (+ 1 2 3) we don't, for example#2021-09-0218:15Joshua SuskaloI think a valid constraint to put on it for now is to only grab the constant keys and values, and provide nothing for these dynamic ones, with the potential in the future that these may be added.#2021-09-0218:15borkdudeok#2021-09-0218:16Joshua SuskaloJust entirely excluding these dynamic ones would help prevent breaking changes by leaving the possibility they're added later, without giving in the meantime a quoted version of it for people to depend on.#2021-09-0218:16borkdudecorrect#2021-09-0218:17borkdudeso the relevant spot where this data is added is somewhere here: https://github.com/clj-kondo/clj-kondo/blob/21de6f46e30c119e82b847330cda5394247e4d36/src/clj_kondo/impl/analysis.clj#L38#2021-09-0218:19borkdudeI think attrs would need an extra :meta key on which we do some processing before we add it to the analysis, if the option {:var-definitions {:metadata true}} is given, I think#2021-09-0218:20Joshua SuskaloI think that would solve all the needs that I have, being able to start with the -T classpath with just . and my own dependencies on the classpath, and then using kondo to get all the metadata to generate the config file. Are there any other hangups I gotta be aware of before I start planning out my tool properly? Like having to figure out how to procure deps or something for kondo to lint them? Or will I be good just using tools.build's facilities for starting a clojure subproces to get the classpath with a set of aliases?#2021-09-0218:20borkdudeyou can just pass the classpath into :lint ["the-classpath"]#2021-09-0218:21Joshua Suskaloawesome#2021-09-0218:25borkdudeUpdated the issue with a summary here: https://github.com/clj-kondo/clj-kondo/issues/1280#issuecomment-911945341#2021-09-0218:27borkdude@suskeyhose Would you like to have a stab at this?#2021-09-0218:30borkdudeIt would also be interesting to see how many times the metadata is dynamic#2021-09-0218:56Joshua SuskaloYeah, I'll take a look at it tonight to see what I can get going.#2021-09-0316:21Joshua SuskaloOkay, so I'm looking at this today @borkdude, and it looks like the line you pointed me to will allow a meta key to come from whatever is passed to reg-var!, so does that mean the rest of this implementation is to just go through all the usages of reg-var! and make them include metadata? It seems like that's the obvious direction to go.#2021-09-0316:21borkdudeyeah I think so#2021-09-0316:22Joshua SuskaloYeah, so there's the namespace/reg-var!, and there's analysis/reg-var!, and it looks like the namespace one is the only one used, and it calls to the analysis one, so I just gotta update the namespace one I think.#2021-09-0316:22Joshua Suskalo'cause that already gets the metadata#2021-09-0316:27borkdudeyeah#2021-09-0316:38Joshua SuskaloHmm. There's a lot of metadata in there that's coming from clj-kondo and not from the original var. Is there a way to select just the stuff coming from the source?#2021-09-0316:41borkdudehmm, like what for example?#2021-09-0316:44borkdudeI'll be back after dinner#2021-09-0316:50Joshua SuskaloActually I think I figured it out#2021-09-0317:04Joshua Suskalohttps://github.com/clj-kondo/clj-kondo/pull/1369#2021-09-0317:05Joshua SuskaloThis is still a "draft" PR, but I'd love to know if this is the right direction, or if I need to be doing something drastically different. I'm thinking then I can have the analysis/reg-var! do the actual filtering of which meta values are allowed, so that no code changes are needed elsewhere if we expand which kinds of meta are allowed.#2021-09-0317:48borkdudeYep, that's going into the right direction. Tests are the next step I think#2021-09-0218:26ericdalloWould be possible to clj-kondo correctly understand a var imported from potemkin and avoid unresolved-var lint?#2021-09-0218:26borkdudeclj-kondo already has built-in support for potemkin#2021-09-0218:27ericdalloHum, we have this lib at nubank that uses potenkim a lot, and when using the vars from its api, I'm getting unresolved-var :thinking_face:#2021-09-0218:28borkdudeRepro welcome#2021-09-0218:29ericdalloI'll try to build a repro!#2021-09-0318:08ericdalloI found the time to repro the issue in a separated repo/branch :) More details here: https://github.com/clj-kondo/clj-kondo/issues/1370#2021-09-0318:12borkdudeoh nice, I didn't know midje had clj-kondo exports#2021-09-0318:12borkdudehttps://github.com/marick/Midje/tree/master/test-resources/clj-kondo.exports/marick/midje#2021-09-0318:12ericdallooh yeah, I merged that last month 😅#2021-09-0318:15borkdudethanks for the repro. I think it should work but I don't know why it doesn't#2021-09-0318:15borkdudehopefully I'll find some time to find out next week or so#2021-09-0318:15borkdudeor if you beat me to it...#2021-09-0318:16borkdudeThe relevant code is in clj-kondo.impl.analyzer.potemkin#2021-09-0318:17ericdallocool! I can try to debug tomorrow :)#2021-09-0318:17borkdudeah, it seems the potemkin code isn't hit at all somehow#2021-09-0318:19borkdudeoh I see, I think it currently only supports potemkin syntax with some vector or so#2021-09-0318:19borkdudeand not a single symbol#2021-09-0318:19borkdudeSo this works:
(ns clojure-sample.api
  (:require
   [clojure-sample.impl.foo]
   [potemkin :refer [import-vars]]))

(import-vars
 [clojure-sample.impl.foo some-func])
#2021-09-0318:20borkdudeso I've done the debugging, I'm sure the fix is pretty easy now#2021-09-0318:20borkdudeI'll past this info in the issue#2021-09-0318:21ericdallooh, really good catch!#2021-09-0318:21ericdalloI tried and it works indeed :)#2021-09-0318:22ericdallothere is this lib at nubank that uses a lot of import-vars with full qualified symbols#2021-09-0318:22borkdudeI think it will be a small change#2021-09-0318:22borkdudefor clj-kondo#2021-09-0318:23ericdalloI imagine that is just make clj-kondo lint this other way of import-vars I think right#2021-09-0318:23borkdudeyes, check if the thing is a symbol and act accordingly#2021-09-0318:24borkdudeSo this is the code:
(defn analyze-import-vars [ctx expr]
  (let [ns-name (-> ctx :ns :name)
        import-groups (next (:children expr))]
    [{:type :import-vars
      :used-namespaces
      (for [g import-groups
            :let [[imported-ns & imported-vars] (:children g)
                  imported-ns-sym (:value imported-ns)]]
        (do (doseq [iv imported-vars]
              (let [iv-sym (:value iv)]
                (prn :reg-var ns-name iv-sym expr {:imported-ns imported-ns-sym
                                                   :imported-var iv-sym})
                (namespace/reg-var! ctx ns-name iv-sym expr {:imported-ns imported-ns-sym
                                                             :imported-var iv-sym})))
            imported-ns-sym))}]))
#2021-09-0318:24borkdudeinstead of destructuring in the let, first check if it's a fully qualified symbol token#2021-09-0318:24borkdudeand then set imported-ns and imported-vars to that#2021-09-0318:24borkdudeelse leave it like it is#2021-09-0318:25borkdudeso g can be either a vector or fully qualified symbol#2021-09-0318:30ericdalloMakes sense 👍 I'll try to fix that and let you know, thanks for the explanation#2021-09-0320:07ericdalloManaged to find a time :) https://github.com/clj-kondo/clj-kondo/pull/1371#2021-09-0320:47borkdudeMerged. I will make a small tweak, but nothing major.#2021-09-0320:48ericdallothank you!#2021-09-0320:51borkdudeOne thing is, I would use qualified-symbol? instead of qualified-ident. Is there a reason you chose the latter?#2021-09-0320:51ericdalloyes, I didn't know about the former 😂#2021-09-0320:52ericdalloI see, the ident checks for keyword as well while the other checks if it's a symbol only#2021-09-0320:58borkdudehttps://github.com/clj-kondo/clj-kondo/commit/13066e47b8418072edc15a853164a2ef73ddc75a#2021-09-0320:58borkdudeteamwork 🤝#2021-09-0320:59ericdallooh that makes sense indeed, good catch#2021-09-0219:37Joshua SuskaloWith regards to the dynamic metadata stuff, is there anything that'd get in the way of checking if all the vars used in the definition are from clojure.core and then evaluating it with sci? I figure an eventual goal for this kinda thing would be to get something that's basically like constexpr evaluation that would just recursively check vars for sci compatibility and then eval them. Although for clarity, I'm not looking to implement this at all for the part I'm looking at tonight. I still want to stick to filtering metadata to constants.#2021-09-0219:38borkdude> is there anything that'd get in the way of checking if all the vars used in the definition are from clojure.core and then evaluating it with sci? yeah, I think you can do that, unrelated to the metadata feature I think#2021-09-0219:39borkdudealso some vars like clojure.string, etc are in sci#2021-09-0219:39borkdudeso as long as the program is pure Clojure, it should mostly work#2021-09-0219:40Joshua SuskaloFair enough. That'll be something that I might think about in the future once the basics of general metadata are into analysis#2021-09-0219:40Joshua SuskaloAlthough at that point it might be worth just putting it into a tracking issue to see if there's interest in it before the work gets put in.#2021-09-0219:41borkdudewhy would you eval the code, what's the goal with that?#2021-09-0219:42Joshua Suskaloto get ^{(+ 2 2) (+ 4 4)} metadata working#2021-09-0219:42Joshua SuskaloLike you mentioned before#2021-09-0219:46borkdudeoh right :)#2021-09-0219:47borkdudeI really do think these are rare cases though, so perhaps some exploration would be good to see often this occurs#2021-09-0220:02Joshua SuskaloYeah, that's why I was thinking about a tracking issue to see for demand#2021-09-0220:07borkdudejust evaluating random expressions isn't safe to do even with SCI, e.g. you can have (defn ^{:foo (range)} dude []) so I wouldn't recommend it#2021-09-0220:10borkdudein the case the metadata isn't a constant, we could also just stringify it#2021-09-0220:11borkdudebut leaving it out for now seems also fine#2021-09-0220:18Joshua SuskaloI think leaving it out for now is the best choice because it leaves us many options for what to do with it in the future.#2021-09-0220:19Joshua SuskaloI'd rather provide something for 80% of cases, and for the 20% provide nothing, than provide something for 100% of cases with a potential for breaking changes to 20% of it.#2021-09-0220:20Joshua Suskalo(although obviously the actual percentage of this kind of thing being uses is lower than that)#2021-09-0220:42borkdudeagreed#2021-09-0316:16Noah BogartI’m using https://github.com/hyperfiddle/rcf to write some inline tests, and i’d like to have :skip-comments also apply to the tests blocks. is that possible?#2021-09-0316:18Noah Bogartoh, nevermind me, this is accomplished by :lint-as#2021-09-0316:18Noah Bogarti had mispelled something 😬#2021-09-0316:18Joshua SuskaloNice#2021-09-0316:19Noah Bogartyeah! every day i’m pleasantly surprised by how powerful clj-kondo is#2021-09-0316:31Joshua SuskaloHey @borkdude do you have a recommended way to build graalvm images? The way I did it a while back was cambada, but I don't know if that's really recommended anymore.#2021-09-0316:35borkdude@suskeyhose do you mean for clj-kondo?#2021-09-0316:35Joshua Suskaloclj-kondo does it with that custom compile script I saw. I'm looking to do a graal distribution of the formatter I'm getting started working on though.#2021-09-0316:36borkdude@suskeyhose I recommend doing it like this: https://github.com/borkdude/jayfu As this will work on all platforms#2021-09-0316:36borkdudeincluding windows#2021-09-0316:36borkdudenothing else is needed than bb + graalvm download#2021-09-0316:36Joshua SuskaloCool#2021-09-0316:36borkdudenot even the clojure CLI#2021-09-0316:36borkdudeand this is quite the pain on Windows CI, the clojure CLI#2021-09-0316:37Joshua SuskaloI'll definitely take a look. In an ideal world here I'd be able to make it a part of my build.clj, but we'll see if that ends up actually being achievable.#2021-09-0316:39borkdudeyeah I think you can also do that, but other than building the uberjar I don't think there is any other benefit to build.clj and building the uberjar already works well without build.clj#2021-09-0316:39Joshua SuskaloYeah, I'm just trying it out for the first time to see how it feels.#2021-09-0316:40borkdudeand you'll still need to install the clojure CLI on the three platforms (including Windows) to make that run#2021-09-0316:40borkdudeexcept when you use the bb clojure one of course#2021-09-0316:40Joshua SuskaloYeah, that's true#2021-09-0316:42borkdudeyou can do bb clojure -Tbuild foo (or whatever the command for this is)#2021-09-0316:42borkdudethe built-in clojure runner is the same as the official Clojure CLI (or at least, it should be)#2021-09-0316:42borkdudebut using the bb task runner is faster for things that don't need a clojure process#2021-09-0316:46JonRHi channel! Wondering if anyone can give me any tips on ignoring function args with clj-kondo? I have found the :exclude-destructured-keys-in-fn-args doc which helps for maps but I'm hoping to find this for normal fn args as well. In particular for multimethods but would be nice to know how to do it system wide too.#2021-09-0317:14Joshua SuskaloWhat exactly do you mean? Do you mean disabling the :unused-binding warning on function arguments?#2021-09-0317:16Joshua SuskaloIn general there are comment forms you can use to disable particular lints for certain forms. Like this:
(defmulti some-multimethod
  (fn #_{:clj-kondo/ignore [:unused-binding]}
      [a b c]
    (keyword a b)))
This won't emit a warning for c being unused.
#2021-09-0317:17Joshua SuskaloAlso @borkdude is that something we'd want to consider as a lint config in general? Like is there a reasonable way to ignore unused bindings for function arguments that are defmulti dispatch functions in particular?#2021-09-0317:18Joshua SuskaloSince generally you wouldn't want the arglist to report that the name of an arg starts with _, since implementations probably use it.#2021-09-0317:28JonRsorry, just saw this repl. Yes! That is pretty much the issue#2021-09-0317:28JonRI'd like to not have to add inline comments all over but be able to just say for multimethods ignore unused arguments#2021-09-0317:29JonRWhich maybe clj-kondo already supports, I just can't find it#2021-09-0317:29Joshua SuskaloThe other thing that I'd consider doing in some cases is to include the :arglists metadata on your functions. That one can have whatever you want in it and isn't linted.#2021-09-0317:29Joshua SuskaloAlthough I don't know if that works on multimethods.#2021-09-0317:30Joshua SuskaloIt doesn't support ignoring unused arguments only in multimethods atm. I was just asking borkdude if that was something feasible to be added.#2021-09-0317:31JonRAh, the :arglists makes sense. That's good to know about#2021-09-0317:47borkdudeyeah, I think we should add that option#2021-09-0318:39borkdude@jon693 Ah there is an issue for it: https://github.com/clj-kondo/clj-kondo/issues/1188#2021-09-0318:39borkdudeYou can upvote it by doing a thumbs up#2021-09-0318:41borkdudeI proposed a solution there and marked the issue as PR welcome, if anybody wants to have a stab at it.#2021-09-0318:42JonROh, I didn't realize the thumbs up is an actual upvote. Do I do that on the initial description?#2021-09-0318:42borkdudeyeah#2021-09-0318:42JonRDone, thanks for sharing the issue#2021-09-0318:42borkdudeGithub allows you to sort by emoticon, which is weird, but that's their only option currently#2021-09-0318:42JonRhahaha, I didn't know that. Pretty funny#2021-09-0318:42borkdudeit's a toy JIRA in this regard, but everybody hates JIRA ;)#2021-09-0318:44JonRI'm in the boat with everybody 🙂 Agreed on GH lacking a bit though. I've been exploring actions for more custom issue and project automation. It's aight#2021-09-0318:46JonRWhile you're here, random question, do you know of a way in emacs with cider to accept clj-kondo suggestions? In particular removing unused imports? Or if not in emacs a way to do that in a script or something#2021-09-0318:47borkdude@jon693 Oh boy, you are in for a treat, try #lsp#2021-09-0318:47borkdudeit builds on the clj-kondo analysis so it knows all about the linting and how to deal with the warnings, you get navigation for free, etc#2021-09-0318:48borkdudeThe command you need in emacs with lsp-mode is lsp-organize-imports#2021-09-0318:49borkdude@ericdallo can tell you more in #lsp where to start. if you install clojure-lsp then you don't need a separate clj-kondo binary installed#2021-09-0318:49borkdudeand you can remove the flycheck stuff#2021-09-0318:49JonRawesome! Thanks so much for this info#2021-09-0318:54ericdalloHey 👋 @jon693 Check https://clojure-lsp.io/features/, any issues/questions, feel free to ask in #lsp :)#2021-09-0318:55JonRThanks @ericdallo, this looks awesome! Gonna try and dig in later and will circle back if I have questions.#2021-09-0415:51ericdalloFYI: Adding clj-kondo support for taoensso/encore https://github.com/ptaoussanis/encore/pull/56#2021-09-0416:10Noah BogartThis is so cool#2021-09-0416:11ericdalloyeah, everytime I face a wrong lint from a lib I try to fix it on the root, this way clj-kondo becomes better with less false-positives :)#2021-09-0418:00Joshua SuskaloIs there a reason that it couldn't be as simple as a {:lint-as {taoensso.encore/defalias clojure.core/def}}?#2021-09-0418:03Joshua Suskalo@UKFSJSM38#2021-09-0418:05ericdalloBecause there is this case:
(defalias other-ns/foo)
#2021-09-0418:05ericdallowhich should expand to (def foo other-ns/foo)#2021-09-0418:37Joshua Suskaloaaaah, I see#2021-09-0419:56ericdalloI made a GH action thathttps://github.com/clojure-lsp/clojure-lsp/blob/master/.github/workflows/bump_downstreams.yml for clojure-lsp, maybe we should do something similar for clj-kondo to for example bump lein-clj-kondo each clj-kondo reelease#2021-09-0420:12borkdudesure!#2021-09-0504:36huygnhi, can I do smthing like this to make hiccups.runtime not showing warning?#2021-09-0504:36huygnnot sure if clj-kondo/ignore works on namespace like /config :thinking_face:#2021-09-0506:49borkdudeWhy are you requiring the namespace if you don’t use it!#2021-09-0506:50borkdudeSorry I meant question mark, fat finger on phone #2021-09-0507:19huygnhiccups.runtime is actually required implicitly by its macro 😂#2021-09-0507:20huygnso if I remoce that line h/html wont work#2021-09-0507:24borkdudeyou can remove the alias#2021-09-0507:25borkdudeand then clj-kondo will not complain#2021-09-0507:27borkdudejust [hiccups.runtime]#2021-09-0507:38huygnnice, thanks!#2021-09-0605:43PratikHi, I was using some of the macros of failjure library - https://github.com/adambard/failjure There are ~13 macros, so what would be the best way to get rid of unresolved-symbol linting warnings? I have tried something like this
{:linters
  {:unresolved-symbol
    {:exclude [(failjure.core)]}}}
but it’s not working(it’s taking clojure-lsp initialization to load forever)
#2021-09-0607:20borkdudeThis config isn't valid, don't wrap this in parens as the symbol isn't fully qualified#2021-09-0607:21Pratikah, okay, then do I need to mention all the 13 macros here?#2021-09-0607:23borkdudeThere may be a better solution. Can you give me an example of such a macro?#2021-09-0607:24Pratik
(defmacro ok->
  "Like some->, but with ok? instead of some?
   (i.e., short-circuits when it encounters a failure)"
  ([start & forms]
   `(if-let-failed? [v# ~start]
      v#
      (attempt-> v# 
this is one of them
#2021-09-0607:25Pratikhttps://github.com/adambard/failjure/blob/master/src/failjure/core.cljc - here you can see more of them#2021-09-0607:25borkdudeYou can use {:lint-as {foo.bar/ok-> clojure.core/->}} here#2021-09-0607:26borkdudewhich gives you better linting than suppressing errors#2021-09-0607:29borkdudeand if you have it all working, you can donate the config to the library itself or to clj-kondo/config so others don't have to re-invent the wheel#2021-09-0607:29borkdude(see https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration)#2021-09-0607:30Pratiksure, I will try to add it for all the macros#2021-09-0607:30borkdudehttps://grep.app/search?q=lint-as.%2Afailjure&amp;regexp=true#2021-09-0607:44Pratik
failjure.core/ok->             clojure.core/->
failjure.core/ok->>            clojure.core/->>
failjure.core/try-all          clojure.core/let
failjure.core/try*             clojure.core/fn
failjure.core/when-failed      clojure.core/fn
failjure.core/if-failed        clojure.core/fn
failjure.core/attempt-all      clojure.core/let
failjure.core/if-let-ok?       clojure.core/let
failjure.core/if-let-failed?   clojure.core/let
failjure.core/when-let-failed? clojure.core/let
failjure.core/when-let-ok?     clojure.core/let
these mostly are the configs, I’ll take a look on the docs you shared later today, to add it in the configs or the library itself
#2021-09-0608:03borkdudeawesome#2021-09-0608:04borkdudeisn't it better to lint if-let* as clojure.core/if-let?#2021-09-0608:10Pratikyes, I will do that(even for when-let*s) also this try* macro was giving error Function arguments should be wrapped in vector.
(defmacro try* [& body]
  `(try-fn (fn [] 
what could be the possible linting option for that?
#2021-09-0608:11borkdudeclojure.core/try?#2021-09-0608:11borkdudeI would lint *-when-let as clojure.core/when-let, not if-let#2021-09-0612:49ericdallo@pratikgandhi1997 in case you want a example of adding the config to the lib itself: https://clojurians.slack.com/archives/CHY97NXE2/p1630770692107400?thread_ts=1630770692.107400&amp;cid=CHY97NXE2#2021-09-0616:28PratikAdded a PR on failjure repo - https://github.com/adambard/failjure/pull/27/files#2021-09-0616:29ericdallo@pratikgandhi1997 in your PR, this way will only work for the failjure repo, not for libs using it#2021-09-0616:30borkdudeSee https://github.com/fulcrologic/fulcro/tree/develop/src/clj-kondo/clj-kondo.exports/com.fulcrologic/fulcro#2021-09-0616:30ericdalloyou need to include in the resources, check https://github.com/ptaoussanis/encore/pull/56 as example, or clj-kondo docs about that https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-09-0616:31borkdudeBut this is a good start, thanks @pratikgandhi1997#2021-09-0616:31Pratikoh, I thought we need to do that only if we are using hooks to do some special thing, let me take a look#2021-09-0616:31borkdudeclj-kondo doesn't import config from the libraries own .clj-kondo directory since that's not on the classpath typically#2021-09-0616:32borkdudeand also not because it can contain config for libraries other than its own sources#2021-09-0616:32ericdalloyeah, your case you don't need any clojure code as you only need the lint-as, but even so you need to add it to the resources#2021-09-0616:32borkdudebut you can refer to the exported config from the .clj-kondo dir so you can use it while developing the lib#2021-09-0616:32borkdudeHere is how you do that: https://github.com/fulcrologic/fulcro/blob/develop/.clj-kondo/config.edn#2021-09-0616:38Pratikokay, I am a little unsure about what to add in the place of com.fulcrologic/fulcro Should it be adambard/failjure in this case? How do we derive it?#2021-09-0616:39ericdalloyes, group-id/artifact-id, just something to not conflict with other configs in classpath from other libs#2021-09-0616:44PratikUpdated the PR with that#2021-09-0616:45borkdudeYou need to remove the intermediate clj-kondo in the directory structure#2021-09-0616:45borkdudesince fulcro has a different project layout#2021-09-0616:46ericdalloThat should work, just not sure if adding to src is a good idea, maybe adding to the resources folder?#2021-09-0616:46borkdudeit has src/java, src/clj, src/clj-kondo#2021-09-0616:46borkdudebut failjure just has src#2021-09-0616:46borkdudeyeah. I think resources is better#2021-09-0616:47ericdalloit would be /resources/clj-kondo.exports/...#2021-09-0616:47ericdallosince resources folder is alredy in classpath as lein adds that folder by default#2021-09-0616:53PratikUpdated the PR, please recheck, I have assumed that we don’t need to give a relative path in the .clj-kondo/config.edn as it’s already on classpath#2021-09-0616:54ericdalloExactly, looks good to me :)#2021-09-0607:10pezWhy do I get Found an opening ( with no matching ) here?
(foo^ :bar)
(It’s not something I need to do, just some test data I have, and I got curious about the problem report.)
#2021-09-0607:14pezClojure is complaining in similar ways. Though it is giving me some more context by first warning: Metadata must be Symbol,Keyword,String or Map.#2021-09-0608:10borkdudeThis is coming from tools reader, I think.
$ plk
ClojureScript 1.10.597
cljs.user=> (foo^ :bar)
Syntax error reading source at (<cljs repl>:1).
Unmatched delimiter ).
#2021-09-0608:10borkdudeit's because the metadata character expected another token after :bar#2021-09-0608:31pezThanks. I should probably fix this in Calva’s tokenizer, but as long as clj-kondo protects the user it is maybe not worth it.#2021-09-0613:37BenjaminI realized my defroutes warning came from clj-joker 😅 is there any reason to use both?#2021-09-0613:38borkdudeI'll let others speak to that#2021-09-0614:29mynomotoI stopped using other linters long ago, clj-kondo is really a joy to use and both the most complete out of the box and most used by the community.#2021-09-0614:45dharriganI too only use clj-kondo thesedays.#2021-09-0614:45dharriganOf course, this channel is heavily biased 😉#2021-09-0617:02PratikI am using https://github.com/seancorfield/honeysql library in my project and when I use it with clj-kondo I am getting few unresolved-var errors, looks like some of those functions use defalias, what would be the best way to suppress/fix them?#2021-09-0617:45seancorfield@pratikgandhi1997 Sounds like you're using HoneySQL 1.0? I'd strongly recommend using 2.0 for any new code.#2021-09-0617:55Pratiklooks like we are using even older "0.9.1" 😐#2021-09-0617:56PratikIs there any doc that explains the compatibility issues between these versions?#2021-09-0617:56borkdudeanyway, defalias linting can be accomplished like this:
{:lint-as {honeysql.util/defalias clojure.core/def}}
if you're not ready to upgrade
#2021-09-0617:57borkdudesame for honeysql.helpers/defhelper clojure.core/def#2021-09-0617:57borkdudewhich we have in our app at work as well still#2021-09-0617:57borkdudeI still have to upgrade the old code. they work side by side#2021-09-0618:00seancorfield@pratikgandhi1997 https://cljdoc.org/d/com.github.seancorfield/honeysql/2.0.783/doc/differences-from-1-x#2021-09-0720:52ProctorAsking here, because as I understand it Clojure-LSP gets its diagnostics from clj-kondo… I get info level diagnostics of Unused public var on my deftests… Is there a config setting to exclude the deftest items from the unused public var check?#2021-09-0720:57borkdude@steven.proctor This is documented over here: https://clojure-lsp.io/settings/#clojure-lspunused-public-var I think it would be reasonable if #lsp didn't flag tests as unused (cc @ericdallo)#2021-09-0720:58borkdude@steven.proctor Your other issue (https://github.com/stevenproctor/cljs-ns-aliasing-troubleshooting) is still in my TODO list :) Is there a corresponding clj-kondo issue in Github for this? I kind of forgot the original problem statement#2021-09-0721:00ProctorI don’t think I put a issue in.. I can create one if not#2021-09-0721:00ProctorI will check#2021-09-0721:01borkdudePlease do. About the unused var: I think the LSP docs show that you can configure this using the :exclude-when-defined-by setting, hopefully clojure.test/deftest works there#2021-09-0721:23Proctorlooks to have done it… needed both cljs.test/deftest and clojure.test/deftest#2021-09-0721:23Proctorthanks!#2021-09-0721:23Proctoralso added the issue to clj-kondo#2021-09-0721:23Proctorthanks3#2021-09-0721:25borkdudethanks a lot, I'll take a look when I find time, I marked it as high priority#2021-09-0721:29ericdalloBTW clojure-lsp already excludes deftest from unused public vars:thinking_face:#2021-09-0721:31ericdallohttps://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/feature/diagnostics.clj#L12-L14 but it's missing cljs.test/deftest#2021-09-0721:33borkdudePerhaps it's a similar issue he was having with respect to cljs.test vs clojure.test ?#2021-09-0721:33borkdudeyou should probably add cljs.test/deftest as well#2021-09-0721:34ericdalloYeah, I just added right now :)#2021-09-0721:34ericdalloit should be working on next clojure-lsp release @steven.proctor so you won't need to exclude manually via config#2021-09-0812:47Proctor:thumbsup:#2021-09-0812:50ProctorYeah, we are in pretty heavy in Node Lambda land, so most things I have been touching are CLJS, but there is a slow attempt to move to CLJ on Java Lambdas (maybe Graaal?)#2021-09-0812:51Proctorbut clj-kondo and clojure-lsp have been fantastic… ♥️ ♥️ ♥️ ♥️#2021-09-0812:52ericdalloNice, thank you!#2021-09-0814:16borkdude@steven.proctor If you need to do some ad hoc scripting with CLJS on Node.js, check out https://github.com/borkdude/nbb#2021-09-0814:18ProctorI saw that… doubt we can move all our Lambdas from figwheel and shadow-cljs to nbb… 😉#2021-09-0814:20borkdudeThat's not what it's for. For lambdas you probably want to have compiled fast CLJS if you want to maximize performance, this is just intended for scripting, perhaps things you put behind cron jobs etc#2021-09-0814:20borkdudeAlthough some people use babashka for lambda as well :)#2021-09-0814:20Proctoryeah, most of the CLJS stuff I am hitting comes from working on things deployed to Lambdas at this point#2021-09-0814:21ProctorWhen/if I hit small things that might need Node, definitely interested in nbb, if I can’t just uses babashka… ;)#2021-09-0814:24borkdudeyeah that's how it's intended to be used#2021-09-0721:53vemvwhat's a good way to teach clj-kondo that (my/with-transaction tx ,,,) takes tx from the environment and rebinds it to a new value? i.e. it macroexpands to (let [~s (foo ~s)] ,,,) where s is an arbitrary symbol (unusual macro shape I know)#2021-09-0721:54borkdude@vemv this macro shape is equivalent to cljs.test/async 😁#2021-09-0721:57vemvdidn't do the trick sadly!
(fn [p]
  (sut/with-transaction p
    1))
will cause an unused-binding to be emitted for the first p
#2021-09-0721:58borkdudecan you give an example of what goes wrong when linting it without configuration then?#2021-09-0721:59borkdudeI don't understand what is the problem if it takes an already existing binding#2021-09-0722:02vemvGood suggestion, removing the macro entirely from .clj-kondo/config.edn gets rids of the warnings I don't think it was like that yesterday, maybe something changed in my WIP. Will create an issue if something persists, hope not thanks!#2021-09-0722:14vemvAnother thing Checking out https://github.com/clj-kondo/clj-kondo/tree/master/analysis . Can clj-kondo be used to forbid the use of a macro? (which is different from using it for forbiding the use of a var, I guess... a macro "goes away" after being macroexpanded)#2021-09-0722:16vemvThis is implementable in Eastwood since a given AST node can be queried for all its "parent macros". It's how if-inside-macroexpansion-of is impl'd Simply curious about what's possible#2021-09-0722:24borkdudeI think that would just similar to this: https://github.com/clj-kondo/clj-kondo/issues/996#2021-09-0722:25borkdudeclj-kondo always sees the macro usage as well, so these rules would apply to macros as well#2021-09-0722:28vemvA possible nuance is that macro usages can be hidden behind other macros' expansions. And so on recursively So one could get false negatives? As long as one isn't doing arbitrary macroexpansions in clj-kondo We chatted briefly about the topic in this channel one day, the conclusion seemed to be that there's no generalized macroexpansion atm#2021-09-0909:41PratikHello, in my clojure test files I am doing [clojure.test :refer :all] from the imports and clj-kondo is warning me about the deftest, is and testing as unresolved symbol. I have fixed the refer-all warning by excluding it in config.edn but I can’t seem to get rid of the unresolved symbol warnings. It’s probably similar to this issue - https://github.com/clojure-lsp/clojure-lsp/issues/316 but I tried clearing the .clj-kondo/.cache and that didn’t work for me#2021-09-0909:42borkdude@pratikgandhi1997 Are you using clojure-lsp?#2021-09-0909:42Pratikyes#2021-09-0909:42borkdudeCan you try from the command line: clj-kondo --lint test/your_test_file.clj#2021-09-0909:42borkdudeand see if the same error happens#2021-09-0909:44Pratikno, while using this command, it doesn’t throw those errors#2021-09-0909:44borkdudeit's a weird issue with clojure-lsp that keeps coming back. please don't throw away any data, since this might be important to get to the root of the problem#2021-09-0909:44borkdudeis your code by any chance open source?#2021-09-0909:44Pratikno#2021-09-0909:45PratikI can try to repro in some test project though#2021-09-0909:45borkdudeplease do, this would be very valuable#2021-09-0909:46borkdudecan you show what is in your .clj-kondo/.cache directory#2021-09-0909:48borkdudeCan you show the contents of 2021.08.07-SNAPSHOT (feel free to leave out any corporate specific data)#2021-09-0909:48Pratikjust created a new app with lein new app hello and in it’s default core_test.clj file got the same unresolved var error#2021-09-0909:49borkdudesweet!#2021-09-0909:49borkdudecan you make a zip archive of this project including the .clj-kondo/.cache ?#2021-09-0909:58borkdudeI can't reproduce the issue on my own system. So it would be valuable to have your .zip file#2021-09-0909:59Pratikaah, looks like that newly created project doesn’t have .clj-kondo folder but still I am getting those errors#2021-09-0909:59borkdudethat's even weirder#2021-09-0910:00borkdudecan you also give the sqlite.db to @UKFSJSM38?#2021-09-0910:00borkdudeperhaps this helps#2021-09-0910:00borkdudeand you are sure you are not using another linter?#2021-09-0910:02PratikSure, I will DM the sqlite.db to @UKFSJSM38#2021-09-0910:03borkdudeperhaps just make a .zip file of the whole project including the sqlite.db#2021-09-0910:03borkdudeand upload it to the issue#2021-09-0910:04borkdudeafter you've done that, perhaps try again with a .clj-kondo directory#2021-09-0910:04borkdudebut please persist the state in a .zip file first#2021-09-0910:05Pratiksure, I will try that. I am using VSCode IDE if that data point helps#2021-09-0910:22borkdudeI think I'm getting now what's going wrong....#2021-09-0910:24borkdude@UKFSJSM38 I think you also need to include https://github.com/clj-kondo/clj-kondo/blob/13066e47b8418072edc15a853164a2ef73ddc75a/script/compile#L20 in the graalvm resources :)#2021-09-0910:24borkdudethis will fix it#2021-09-0910:25borkdudeyour clojure-lsp doesn't have the built-in clj-kondo caches for clojure.test, etc.#2021-09-0910:25borkdude@UKFSJSM38 feel free to do a similar PR for clj-kondo to move these settings to META-INF#2021-09-0910:25borkdudethen clojure-lsp will automatically benefit from this too#2021-09-0910:26borkdudeI'll also respond in the issue#2021-09-0910:28borkdudealso created a new issue: https://github.com/clojure-lsp/clojure-lsp/issues/548#2021-09-0912:12ericdalloGood debugging! Yeah, that makes sense now, I'll try fix it for the next release!#2021-09-0913:31ericdalloFixed on clojure-lsp master @pratikgandhi1997! it should be available on next release#2021-09-0913:32PratikAwesome! Thanks for the super-quick fix 🙂#2021-09-0913:28lassemaattaI was playing around with the --parallel option to see how much it improved linting performance, but I fail to see any difference. My cpu monitor also reports that only a single cpu core is being utilized while linting. Is this expected or have I messed up something?#2021-09-0913:29lassemaattaI'm doing just clj-kondo --parallel --lint src/.#2021-09-0913:33Noah Bogarthow big is the src folder?#2021-09-0913:35lassemaattavery big 🙂#2021-09-0913:37lassemaattanot sure if this is a useful data point, but if I lint the src folder from the babashka repo it takes about 520 +/- 5 ms, regardless of --parallel#2021-09-0913:46borkdude@U0178V2SLAY sources are grouped per directory and jar file, this is why you aren't seeing any difference#2021-09-0913:46borkdudethis is specifically for linting classpaths#2021-09-0913:46lassemaattaAh, I see, thanks!#2021-09-0913:46borkdudeyou could speed it up by linting several different directories separately#2021-09-0913:46borkdude--lint src/dir1:src/dir2 etc#2021-09-0913:48lassemaattaHmm, I’m almost certain I tried that. I’ll retry later and see if I can spot a difference#2021-09-0913:53borkdudeThis:
find src -type d | xargs clj-kondo --parallel --lint
vs this:
find src -type d | xargs clj-kondo --lint
seems to make a difference
#2021-09-0913:54borkdudestrangely just clj-kondo --lint src is faster than both, not sure why#2021-09-0914:10lassemaattahow does clj-kondo handle the situation where you supply "overlapping" directories? e.g. --lint first:first/second:first/second/third:... ?#2021-09-0914:11lassemaattabecause I think that what happens if you use find ... , I guess?#2021-09-0914:11borkdudeah I see yes#2021-09-0914:11borkdudeclj-kondo doesn't handle that#2021-09-0914:11borkdudeit just lints whatever you give it#2021-09-0914:12lassemaattayeah, I assumed that when I got a bunch of "redefined vars" warnings when trying that find invocation :)#2021-09-0914:12borkdude:)#2021-09-0914:12borkdudeit could probably filter this out, but I don't think it's very common to do it like this#2021-09-0914:16lassemaattabut back to the original issue: if I supply several sibling folders with --lint src1:src2:..:srcN -> --parallel improves the performance#2021-09-0914:19lassemaattaso I guess it's working as intended, but leveraging the benefits of --parallel when linting a project itself is tricky. which is fine, as the typical performance of clj-kondo is fast enough for most projects#2021-09-0914:21borkduderight#2021-09-0914:21borkdudealso when you use --dependencies it will skip already linted .jar files with is another perf optimization#2021-09-0918:26Noah Bogartis a hook the best way to indicate that a macro creates multiple defn s?#2021-09-0918:35borkdudedepends on the macro#2021-09-0918:36borkdudebut with hooks you get the most power, other options work if you're lucky#2021-09-0918:47borkdudenote that there is now also an "easy" hook option which allows you to write a macro just like you would do it in clojure#2021-09-0918:56nateis that the :analyze-call stuff?#2021-09-0918:56borkdudethat's the "hard" option, the easy option is :macroexpand#2021-09-0918:57borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand#2021-09-0918:58nateah cool, I'll check that out#2021-09-1006:25pezHello, sorry for being lazy. Short of time! 😄 Is there a comment marker I can put in a file to stop linting of it?#2021-09-1007:47borkdude@pez Can you give more context? I think we've been over this before with the Calva REPL window. Is this another use case?#2021-09-1012:33Noah BogartIn javascript, you can write // eslint-disable and linting will stop until you write eslint-enable, so putting that at the top of the file effectively ignores the whole file#2021-09-1012:34Noah BogartHere’s a good description of what's possible: https://stackoverflow.com/a/56719951/3023252#2021-09-1012:36borkdudeWe already have this in clj-kondo but only on the level of forms#2021-09-1012:36borkdudeAnd there is https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#include-and-exclude-files-from-the-output#2021-09-1012:37borkdudeso I'm asking questions to learn about the context of the problem#2021-09-1012:50Noah BogartSure, I don’t mean to demand that kondo has this, just noting what might be the reasonable expectation of functionality#2021-09-1015:06pezSo, I am not expecting this functionality. 😀 I have a lot of test files for testing various Calva features. Some of them have a lot of small forms and I create new files quite often. It would just be very convenient if I could add a comment to make the files more readable. It's fine with configuring it in some other file as well. Even if I would find a comment more easy at hand. #2021-09-1015:07borkdude@pez yeah, I think you can configure that in .clj-kondo/config.edn right now#2021-09-1015:08borkdudeyou can also put everything in your favorite comment and then add #_:clj-kondo/ignore on that, if that makes sense#2021-09-1015:29Noah BogartOr :skip-comments in config, which I like a lot #2021-09-1015:31pezThanks!#2021-09-1415:44borkdude#2021-09-1419:55Joshua SuskaloWhen can we get support for :as-alias in clj-kondo?#2021-09-1420:09borkdude@suskeyhose Where is the documentation of that?#2021-09-1420:10Joshua Suskalohttps://clojure.atlassian.net/browse/CLJ-2123 https://github.com/clojure/clojure/commit/f96eef2892eaef55dbbdbf7f3b4b818be06f6ddd#2021-09-1420:32borkdudeok that doesn't look too complicated to support, I'll have a look soon. welcome to make an issue#2021-09-1420:33Joshua Suskalocool#2021-09-1420:37Joshua Suskalohttps://github.com/clj-kondo/clj-kondo/issues/1378#2021-09-1512:07borkdude@suskeyhose it's been released#2021-09-1514:13Joshua Suskaloawesome#2021-09-1518:50seancorfieldQ: so I'm using http-kit.client and it uses a macro to define a bunch of functions like put, get, post, etc in terms of a generic request function -- and clj-kondo is reporting http/post etc in my code as unresolved. Is there a way to tell it about those vars defined via macros?#2021-09-1519:03nateI've run into the same issue with http kit, and with an internal library that creates functions in a macro.#2021-09-1519:11nateI wonder if it would be possible to an analyze-call for the creating macro and turn it into a bunch of defns#2021-09-1519:53borkdudeUsually you can solve this using :lint-as#2021-09-1518:50seancorfield(this seems to be the first time I've managed to get LSP/clj-kondo to fully rescan our source code in a long while -- see my struggles in #lsp for that)#2021-09-1519:52borkdude@seancorfield Yeah, you can use {:lint-as {org.httpkit.client/defreq clojure.core/declare}} and then re-scan your project#2021-09-1519:54borkdudeThis config can also be contributed back to the library using config exports/imports#2021-09-1519:54borkdudeSee https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-09-1519:56borkdude@seancorfield You can force re-scanning your project by removing .lsp/.cache and then re-opening your editor, or does clojure-lsp automatically re-scan your project upon config changes @ericdallo?#2021-09-1520:05seancorfieldI thought I could just change deps.edn to force a rescan but that doesn't seem to have done it (I temporarily added the http-kit dep directly to the project deps.edn file -- it's just a transitive dep via :local/root otherwise) but I suspect LSP thinks it has already scanned http-kit...?#2021-09-1520:05borkdude@seancorfield
rm -rf .lsp/.cache
#2021-09-1520:09seancorfieldThat seems unfortunately brutal but I guess it'll work 🙂#2021-09-1520:18borkdude@seancorfield Perhaps @ericdallo has a less brutal way ;)#2021-09-1520:20seancorfieldYeah. Rebuilding the entire cache worked. It would be unfortunate if that's the only option after updating clj-kondo's config.#2021-09-1520:20borkdudeagreed#2021-09-1520:55ericdalloIf you change your deps file, clojure-lsp should certainly scan the project but only in the next startup, not automatic#2021-09-1520:56ericdalloabout updating the clj-kondo config there is this issue: https://github.com/clojure-lsp/clojure-lsp/issues/331#2021-09-1520:56borkdude@ericdallo clj-kondo already has a hashing function for internal use to ignore already linted deps when the config has changed#2021-09-1613:51ericdalloWould you mind sharing the function on the issue please? https://github.com/clojure-lsp/clojure-lsp/issues/331#2021-09-1613:53borkdudedone#2021-09-1613:54ericdallothank you!#2021-09-1520:58borkdudeperhaps you can use it for inspiration#2021-09-1521:46seancorfieldOh, nice! Glad to know there's an issue. Also, good to know that if deps.edn changes, clojure-lsp will rescan at next startup -- I had hoped it would kick off a scan once the file changed... is there a way to "force" (encourage) clojure-lsp to rescan without restarting/reloading the editor? (I'm using VS Code/Calva if it makes a difference)#2021-09-1521:47borkdudeI would also like to have this in emacs#2021-09-1521:51borkdude@seancorfield fwiw, a lot of libs are already providing config for clj-kondo. these are some examples: https://github.com/clj-kondo/clj-kondo/issues/1383 these configs are automatically imported by clj-kondo into the .clj-kondo directory when lsp indexes your deps, but you should still "opt in" to them by editing your deps.edn . if you have any libraries with macros that need config, you can consider doing the same and it will just work for anyone who uses your libraries.#2021-09-1522:03ericdallothere is lsp-workspace-restart for emacs, but for vscode I think only the reload window is available#2021-09-1522:06borkdudeah is that it, yeah I've been using that, thanks#2021-09-1522:29seancorfield@borkdude Thanks. I probably ought to look at how clj-kondo views my various libraries and go ahead and do that "properly" for them...#2021-09-1616:29naomarikHow would I completely ignore a form in my .clj-kondo file, similar to the comment?
#_:clj-kondo/ignore
(encore/cond
  :let [a 1]
  a)
#2021-09-1616:31borkdude@naomarik you would like to ignore one form, but by configuration in .clj-kondo/config.edn? I'm not sure if I got that correctly#2021-09-1616:33naomarikyeah just to remove all the errors from taensso.encore/cond macro#2021-09-1616:35naomarikhttps://github.com/ptaoussanis/encore/blob/master/src/taoensso/encore.cljc#L266#2021-09-1616:40borkdudeSo, the error is primarily unresolved symbol I think?#2021-09-1616:41borkdudecan you provide more examples? I suspect there is a better solution#2021-09-1616:43naomarikyup exactly#2021-09-1616:44naomariki wouldn't mind ignoring it outright and not have linting, but only way I can do that seems to be with that comment#2021-09-1616:45borkdudealright, for now:
{:linters {:unresolved-symbol {:exclude [(taoensso.encore/cond)]}}}
#2021-09-1616:46borkdudein .clj-kondo/config.edn#2021-09-1616:47naomarikahh I was close to that
:linters {:unresolved-symbol {:exclude [(encore/cond)]}}
#2021-09-1616:47naomarikall good now, was missing the full namespace 🙂#2021-09-1720:03royalaidHey @borkdude love kondo! I’m trying to extend to catch all of my calls to js/console.log . I figured this would be like any other hook but it doesn’t seem to be picking up the usages in my project#2021-09-1720:09borkdude@royalaid the hooks are currently only for clojure code, not for interop. if you could like to find calls like this, you could either use grep or https://github.com/borkdude/grasp or similar.#2021-09-1720:11royalaidSo it won’t pick up forms like the ones in the js ns?#2021-09-1720:15borkdudeI don't think so (but worth a try :P)#2021-09-1720:15royalaidYeah it wasn’t getting them so wanted to make sure I wasn’t missing some, seems like your assumptions are correct 😢#2021-09-1722:44azHi everyone. I’ve been struggling for hours to try to build a hook, but I’m really stuck on this one. Any tips to getting something like this working with kondo?
(defmacro for-indexed [[item index coll] & body]
  `(for [i# (range (count ~coll))]
     (let [~item (nth ~coll i#)
           ~index i#]
       
This is how far I’ve been able to get but I still get linting errors. Unused binding coll, item and index
(ns hooks.for-indexed
  (:require [clj-kondo.hooks-api :as api]
            [clojure.edn :as edn]))

(defn for-indexed [{:keys [:node]}]

  (let [[bindings body] (-> node :children rest)
        [item index coll] (:children bindings)

        new-node (api/list-node
                  (list*
                   (api/token-node 'let)
                   (api/vector-node [item index])
                   body))]
    {:node new-node}))
Any ideas?
#2021-09-1807:53borkdude@limix If the struggle is too real, then you can also just re-use that macro with the :macroexpand hook :) It usually helps me to put a println with the new-nodeto debug the resulting node#2021-09-1808:14borkdudeE.g. when I lint:
(ns bar
  (:require [foo :as foo]))

(foo/for-indexed
 [itm idx [1 2 3]]
 )
then I see <list: (let [itm idx])>as the expansion and I get an unresolved idxbecause that's the right value which is referring to something unknown.
#2021-09-1808:36borkdude@limix So this implementation works:
(defn for-indexed [{:keys [:node]}]

  (let [[bindings & body] (-> node :children rest)
        [item index coll] (:children bindings)
        new-node (api/list-node
                  (list
                   (api/token-node 'for)
                   (api/vector-node [item coll])
                   (api/list-node
                    (list*
                     (api/token-node 'let)
                     (api/vector-node [index (api/token-node 0)])
                     body))))]
    {:node new-node}))
I'm just generating <list: (for [itm [1 2 3]] (let [idx 0] itm))> there, to keep it simple, so I'm making a let with idx bound to 0, so if you don't use this binding then clj-kondo will report the binding as unused.
#2021-09-1817:03azThank you for this @U04V15CAJ - I have been trying to wrap my head around this. I’ve been tweaking your solution to try to better understand how it works. I’m confused as to why the variadic form & body works and without it returns all the same finding of no item, index coll. Also, I’m using calva and I need to restart vscode to get any changes in clj-kondo. Instead now, I’ve been linting via command line and using jet (excellent tool btw) to see what’s happening. Wondering if you have tips on a better workflow for building hooks. Lastly, I am trying to use the macroexpand hook. where would I see the output of this? When I run
clj-kondo --lint src/rdd/components/recipe/recipe_editor/testing.cljs --config '{:output {:analysis true :format :edn} :linters {:for-indexed/missing-index {:level :error}} :hooks {:macroexpand {rdd.utils.for-indexed/for-indexed script/for-indexed}}}' | jet --pretty
I’m not seeing anything like you mentioned when you lint <list: (let [itm idx])> Thanks again for all the amazing work
#2021-09-1817:21borkdudeWhen you use bindings & body then body is a list of expressions, else it's a single expression#2021-09-1817:21borkdude(expression = node here)#2021-09-1817:22borkdudeyou will only see output if you prn something in your macro#2021-09-1817:22borkdudeand if you configured it correctly#2021-09-1817:23borkdudeyou can push a minimal repro perhaps so we know we're talking about the same thing#2021-09-1808:37borkdudeNote that I used & body instead of body as well#2021-09-1914:16ericdalloI think I found one more potemkin corner case that I think we should consider on fixing it on clj-kondo 🧵#2021-09-1914:17ericdallohttps://github.com/metabase/metabase/blob/master/test/metabase/test.clj#L132-L145#2021-09-1914:17ericdalloyou can pass the first arg as the alias of the namespace and then the symbols#2021-09-1914:18ericdalloI found that a lot of things doesn't work on metabase because this issue#2021-09-1914:18ericdalloit should not be hard to support it I think#2021-09-1914:19ericdallonot sure though how to get the namespaces from the alias on clj-kondo code at that time#2021-09-1915:18borkdudeah right so an alias instead of the full namepace right?#2021-09-1915:18ericdalloYes#2021-09-1915:18ericdalloAlso, it's possible to pass multiple vectors, but I think kondo is handling those already#2021-09-1915:18borkdudeok, I'll take a look#2021-09-1915:46borkdude@UKFSJSM38 should be fixed on master#2021-09-1915:46ericdallooh that was fast :)#2021-09-1915:47ericdallothanks, I'll will try#2021-09-1916:02borkdude
clj-kondo-2021.09.16-20210919.160121-5
#2021-09-1916:08ericdalloit worked! thank you! FYI @U11BV7MTK this should help with a lot of false positives on metabase , probably the rest is just macros that should be configured on clj-kondo side with lint-as and custom hooks :)#2021-09-1916:08ericdalloI'll include this clj-kondo bump on the next clojure-lsp release, thanks for the help @U04V15CAJ#2021-09-1923:06ericdalloOne more potemkin issue 😅 now related to kondo configuration 🧵#2021-09-1923:08ericdallousing the metabase as example again, I found a issue related to custom configuration like :lint-as for macros that are being used by potemkin#2021-09-1923:11ericdalloFor example: metabase has https://github.com/metabase/metabase/blob/master/test/metabase/test/data.clj#L204 dataset macro that I want to lint-as def . I added this to the .clj-kondo/config.edn :
{:lint-as {metabase.test.data/dataset clojure.core/def}}
but that doesn't seems to work for the usages that use potemkin under the hood, for example https://github.com/metabase/metabase/blob/master/test/metabase/query_processor/pivot_test.clj#L86. This only works if I change the lint-as to the namespace that import the vars with potemkin like:
{:lint-as {metabase.test/dataset clojure.core/def}}
#2021-09-1923:11ericdalloThe user could add both namespaces to the lint-as is just that seems something clj-kondo could be smart and already check for the config for that imported potemkin var, right? Also, the same happens for hooks configuration#2021-09-1923:12ericdalloSorry for bringing a lot of bugs, is just that I found metabase a good project to find/test LSP and see what doesn't work/could be improved :)#2021-09-2009:10borkdudeI agree this would be clever but this is a little bit complicated#2021-09-2009:10borkdudehow many macros is this about#2021-09-2009:12borkdudewe need to read the cache in an earlier phase to support this so it's not a trivial change#2021-09-2009:15borkdudeI added a TODO test: 0ae0e51158570d3c94be7c0c7b16c0c8cc593ecb You're welcome to make an issue about this but I don't consider this high priority for now (weighing the complexity vs how much effort it is to configure this)#2021-09-2012:17ericdalloSure, that's fair, I only found 3 macros until now in the metabase that fall into this issue, but I agree this is no high priority#2021-09-2111:26pithylessFWIW, I wrap a lot of library macros and functions this way (the indirection is useful if you want to augment or modify the original behavior systematically throughout your application) and sometimes end up adding both the wrapper and the original macro to clj-kondo. It's not pretty, but it has not been a deal-breaker so far.#2021-09-2111:28pithyless^ I don't think this is inherently related to potemkin; but I may be wrong and some of my config linters are no longer necessary.#2021-09-2111:32borkdudeI'm not sure what you meant by the last sentence: you no longer need config which you needed before?#2021-09-2113:52pithyless
{:lint-as
{metabase.test.data/dataset clojure.core/def
 metabase.test/dataset clojure.core/def}}
^ I was thinking that ideally one of these would be enough, and the other could be inferred.
#2021-09-2113:53borkdudeyes, that was what this discussion was about.#2021-09-2113:56pithylessYep, I wanted to just add a datapoint that I come across this problem in my own projects, it'd be nice if it were fixed, but it's not something I consider a very thorny issue that is a pain to deal with it. If that was not obvious, sorry for adding to the noise. :)#2021-09-2113:58borkdudethanks for the input. it requires an architectural change in clj-kondo, it might be fixed one day, welcome to make issues, but low priority for now#2021-09-2114:03borkdudeI wonder if would be useful to have a config to make clj-kondo clear if two things should be treated the same, but this is already what :lint-as is for more or less ;)#2021-09-2221:27JonRAre lsp-clojure or clj-kondo used for doc generation? Not sure if that's a use case but I was just wondering if I could do something like inspect my source for all implementations of a multi-method for example. Would be awesome if I could make a commit hook to generate an md file of usages for example.#2021-09-2221:29borkdude@jon693 You might be able to use the analysis data in clj-kondo for this: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md I'm not sure if it reports all multi-method usages correctly currently. And once you know the locations, you could use another tool (like rewrite-clj or a more basic approach) to cut out the code and display it.#2021-09-2221:37JonRawesome @borkdude thanks! I'll check those out#2021-09-2415:50ericdalloI'd like to know if clj-kondo can access config paths inside a config-path of a external lib, let me explain the case 🧵#2021-09-2415:51ericdalloAt Nubank we have a lot of services using something lke this at each service:
{:config-paths ["nubank/a" "nubank/b" ...]} ; a lot more
we would like to centralize that in a dev lib that when bumped, it will already include all those config-paths. avoiding the need to update config-paths for each service, since we already have a bot that bump libs for all services
#2021-09-2415:52ericdalloso I'd like to have a lib that will have all the :config-paths and then each service would just include a:
:config-paths ["nubank/base"]
#2021-09-2415:52ericdalloI tried that, but clj-kondo is not finding the nubank.a hooks because they are problably not in the same folder#2021-09-2415:52ericdallodo you see any easy way to do that?#2021-09-2415:53ericdalloThe idea behind this is to have one simple config.edn that is common for all libs, instead configuring each one manually#2021-09-2415:54ericdallothe ~/.config/clj-kondo/config.edn is not enough as users need to manually have that on their machines/CI#2021-09-2415:54borkdudeyes, this should already work#2021-09-2415:54borkdudebut the config-paths are always relative from the config.edn where you define it#2021-09-2415:55ericdalloexactly, I'm not finding the correct one so and getting:
WARNING: file nubank/state_flow.clj not found while loading hook
for example
#2021-09-2415:56borkdudeyou can include the base config in a library and when this library is linted then the config is copied to your .clj-kondo folder#2021-09-2415:56borkdudeand then you can include it#2021-09-2415:57ericdallothat's exactly what I want, probably some wrong relative config-paths, I'll double check the paths after the copy#2021-09-2415:58ericdalloOh, your suggestion to check the copied folder indeed helps, let me fix it#2021-09-2416:02ericdalloIt worked :) I needed to change the base to somethine like this:
{:config-paths
["../a"
 "../b"
 "../c"
 ...
 ;; non nubank clj-kondo configs
 "../../marick/midje"
 ...]}
#2021-09-2416:02ericdalloThank you!#2021-09-2416:02borkdudeah ok :)#2021-09-2607:51BenjaminI have a macro like let I guess there is a way to tell clj-kondo that the first arg is a bindings vector?#2021-09-2609:12borkdude@benjamin.schwerdtner Yeah: {:lint-as {your.ns/your-let-macro clojure.core/let}}#2021-09-2801:19Joshua SuskaloI take it that the attribute map doesn't git linted?#2021-09-2801:21Joshua SuskaloOtherwise I'd kinda like being able to output the attribute map, but map nodes aren't available in the clj-kondo version of rewrite-clj#2021-09-2807:09borkdude@suskeyhose can you be more specific with an example? Attr maps should be linted. Also map node has been added recently I think #2021-09-2808:07vemvI made this mistake yesterday: (set-error-handler! a (fn [^Exception e] i.e. wrong arity for a well-known callback. I recall clj-kondo being helpful for similar mistakes, would it be at hand to also catch this one?#2021-09-2808:08borkdudeWe could add support for that yes#2021-09-2808:09vemvnice!#2021-09-2808:10borkdudeIssue welcome!#2021-09-2808:11vemv:thumbsup: will was hesitant at first, didn't want to ask for too much#2021-09-2813:54Joshua SuskaloOh that's good if map node has been added#2021-10-0507:41wdullaerI've got a question about the new 'loop-without-recur' linter#2021-10-0507:42wdullaerwe're pretty heavy users of manifold, and use it's version of recur from time to time#2021-10-0507:42wdullaerwe have d/loop aliased to core/loop#2021-10-0507:42wdullaerbut then the new linter will complain because it doesn't recognise the d/recur statement as a valid recur#2021-10-0507:42wdullaeradding an alias for d/recur to core/recur doesn't fix this#2021-10-0507:43wdullaerI've taken a look at the code for the linter, but couldn't immediately see where it goes wrong#2021-10-0507:56borkdude@wdullaer ah I see, I think that warrants an issue#2021-10-0507:57wdullaeralright, I'll post one in a minute#2021-10-0507:58wdullaerlike I said: I took a look, but it's too subtle for my noob skills 😉#2021-10-0507:59borkdudeno worries#2021-10-0509:41wdullaeron closer inspection (trying make a minimal reproduction case), it's probably more due to some other deferred control flow mechanisms#2021-10-0509:42wdullaerkondo handles it fine with the added alias for recur in "normal" scenario's#2021-10-0509:43wdullaerbut it gets confused if it's part of a d/catch (which takes a function), or if the d/recur is wrapped in a function that schedules it after a timeout#2021-10-0509:46wdullaer
(d/loop [] (side-effect :here) (mt/in 1000 d/recur))
#2021-10-0509:52borkdudeoh right :)#2021-10-0509:53borkdudeperhaps it's better to just write a hook for d/loop then. hooks have gotten a little easier with the new :macroexpand option#2021-10-0509:53borkdude^ @wdullaer#2021-10-0509:54borkdudeor you could just lint d/loop as clojure.core/let and be done with it#2021-10-0509:56wdullaeryeah, I think I'd actually have to write hooks for the control flow mechanisms (kondo also doesn't recognize normal loop and recur here)#2021-10-0509:56wdullaerso sorry for the noise#2021-10-0509:57borkdude@wdullaer lint-as let - isn't that a much easier solution?#2021-10-0509:57wdullaeroh yeah, it's what I'll be doing 🙂#2021-10-0509:58wdullaerI was just thinking out loud: the root cause is that kondo doesn't really understand that the arguments to stuff like d/catch are called later#2021-10-0509:58wdullaerbut it's also a bit unreasonable to expect it to do so 🙂#2021-10-0510:00borkdudejust for my understand, could you provide an example of that catch code?#2021-10-0510:01wdullaerthe example I gave earlier with mt/in is one -> kondo doesn't realize d/recur is executed later, I'll prepare a gist with d/catch#2021-10-0510:04wdullaerhttps://gist.github.com/wdullaer/d373ff38012cb247e8b1d6d600447efc#2021-10-0510:05wdullaeressentially this retries a request infinitely until it succeeds, throttled by a rate-limiter#2021-10-0510:05borkdudecould you add require etc so I can understand what clj-kondo does not lint correctly?#2021-10-0510:13borkdudeE.g. I don't see any warnings here:
(ns private.tmp.repro
  (:require d log http))

(defn run-with-rl [x y] x y)

(declare endpoint http-opts bucket)

(d/loop []
  (->
   (d/chain (run-with-rl (partial http/get endpoint http-opts) bucket)
            :body)
   (d/catch #(do (log/error "failed to execute request:" %)
                 (d/recur)))))
#2021-10-0510:13borkdudebut you probably are referring to the loop without recur#2021-10-0510:14borkdudeyeah that's really just written for clojure's loop/recur syntax#2021-10-0510:25wdullaerindeed, I don't think it's reasonable to expect kondo to figure this out (without some serious hints from hooks)#2021-10-0510:26wdullaerI jumped to conclusions because it always failed on d/loop, trying to make a minimal repro case provided clarity 🙂#2021-10-0510:27borkdudeok, all clear then :)#2021-10-0510:27wdullaerthanks for your time!#2021-10-0610:56Jakub Holý (HolyJak)Hi! Does kondo not support the transducer arities? Here it complains > clojure.core/map is called with 1 arg but expects 2, 3, 4 or moreclj-kondo(invalid-arity) Code: (into [] (map :val) [{:val 1}]) Searching for "transduce[r] in issues yield nothing. (Kondo v. 2021.09.25)#2021-10-0610:58borkdudeI don't see any error for that example#2021-10-0610:59borkdude@U0522TWDA Can you try on the command linting only that example? It could be a hiccup in your editor or so#2021-10-0610:59Jakub Holý (HolyJak)yes, I am using Calva, perhaps it is doing something weird there#2021-10-0611:00Jakub Holý (HolyJak)yes, CLI is ok#2021-10-0611:02borkdudeperhaps try closing and reopening the file or so#2021-10-0615:27ericdallois it possible to exclude some linters from clj-kondo for a whole namespace but via config?#2021-10-0615:27ericdallolike I want to exclude unused-namespace for the user namespace#2021-10-0615:28ericdallobut I'd like to do that via config, not commenting on the code as this config is shared for a lot of projects#2021-10-0615:28ericdallosomething like:
{:unused-namespace {:exclude-ns [user]}
 :unused-referred-var {:exclude-ns [user]}}
#2021-10-0615:29borkdudenot supported right now. I think there are various ways to go about this. we could e.g. also support {:ns-config {user {:unused-namespace {...}}}#2021-10-0615:32ericdallohum, instead of configuring for each linter, kind of configure which linters you want exclude for a ns?#2021-10-0615:33borkdudeno I mean: this would allow you to provide an ns-local config without touching the code#2021-10-0615:34ericdallooh got it#2021-10-0615:34ericdallowe could do much more than excluding right#2021-10-0615:34ericdallobut configuring whole kondo for specific ns#2021-10-0615:35borkdudethis would allow you to do the same as (ns foo {:clj-kondo/config ...})#2021-10-0615:35borkdudebut then in your config file#2021-10-0615:36ericdalloI didn't even know a :clj-kondo/config exists 😂#2021-10-0615:36ericdallolooks good#2021-10-0615:36borkdudeoh I thought you were referring to that#2021-10-0615:37ericdalloi was referring to supress linter via code with {:clj-kondo/ignore} but yeah, your idea would allow do more than just supress lint#2021-10-0615:37borkdudeso instead of changing each linter to support an ns, we could support providing configs per ns#2021-10-0615:37borkdudewhich is only a small change really#2021-10-0615:37ericdallolooks really good#2021-10-0615:37borkdudesince the code for reading config is already there#2021-10-0615:37borkdudein the namespace form logic#2021-10-0615:38ericdalloalso, do you think would be possible add support for something like:#2021-10-0615:38ericdallo
{:ns-config {".*-config" {:unused-namespaces {...}}}}
#2021-10-0615:38ericdalloadd regex for those namespace match#2021-10-0615:39ericdallosince at Nubank, we have a pattern of <service-name>.config and a lot of ns#2021-10-0615:39ericdallothen the common config code would catch the service name always#2021-10-0615:39ericdallodoes that makes sense for you?#2021-10-0615:39borkdudeyeah, although having a regex as a key in a map doesn't really make sense to me :)#2021-10-0615:40borkdudebut the idea sounds good#2021-10-0615:40ericdalloyes 😅#2021-10-0615:43borkdudecan you make an issue?#2021-10-0615:44borkdudebtw this use case is quite rare. I'd like to discuss with you why you would like to suppress unused namespaces only in certain namespaces#2021-10-0615:47ericdalloSure#2021-10-0615:47ericdalloit's actually quite simple, at nubank we have a service template that all services follow, for example the user ns has only this:
(ns user
  (:require [clojure.tools.namespace.repl :refer [refresh refresh-all]]
            [common-core.misc :as misc]))
#2021-10-0615:48ericdallofor REPL functions be easily available after jack-in
#2021-10-0615:48ericdalloAlso, I can see we easily creating custom linters for specific namespaces!#2021-10-0615:49borkdudefor the user ns I can understand, but why for the others?#2021-10-0615:50borkdudeyes, with :clj-kondo/config in metadata you can do this for specific namespaces in your template#2021-10-0615:50ericdallowe probably wouldn't want to exclude linters for other namespaces, but configure custom linters for other namespaces via this new config flag specific for some namespaces would be cool#2021-10-0615:51ericdallobut it would require the regex support as well#2021-10-0615:51ericdallobut for now, just having a way to exclude some linters for a namespace via config is quite enough#2021-10-0615:52borkdudeso I think if you have a template, just add the config to the template, like:
(ns user {:clj-kondo/config '{:linters {:unused-namespace {:level :off}}}})
#2021-10-0615:53ericdalloyes, that would work for new services, but other hundreds of old services we would need to do some kind of migration 😅#2021-10-0615:53borkdude:)#2021-10-0615:53borkdudethat's a good explanation#2021-10-0615:53ericdallowe already have a custom config created recently for all services#2021-10-0615:53ericdallousing the clj-kondo export feature#2021-10-0615:54ericdallosomething like {:config-paths ["nubank/codestyle"]} which has all the common configuration for clj-kondo and etc#2021-10-0615:54ericdalloso my idea was to just add the exclude for user on that common config you know#2021-10-0615:57borkdudeyeah that's a good idea#2021-10-0615:57borkdudeso the idea is: we should support the namespace local config (override) but outside the scode#2021-10-0615:57ericdalloCool, I'll open the issue then#2021-10-0615:57borkdudeand with regex#2021-10-0616:06ericdallohttps://github.com/clj-kondo/clj-kondo/issues/1398#2021-10-0618:10deletedis this a known issue, where clj-kondo doesn't see this var being set? https://github.com/metosin/ring-http-response/blob/master/src/ring/util/http_response.clj#L1177-L1180#2021-10-0618:16borkdudeI think it should recognize this one in the latest clj-kondo#2021-10-0618:18borkdudeif it doesn't, could you make an isolated repro?#2021-10-0618:47borkdudethanks :)#2021-10-0814:39sheluchinI've been dealing with a bug [0] in my code that ultimately came down to a single letter typo. It was a typo in the options map that got passed to a function: :request-middlware. I'm not sure if this is kondo territory - excuse me if not - but is there any way to get a linter warning in such cases? [0]: https://clojurians.slack.com/archives/C68M60S4F/p1633611309397500#2021-10-0814:41borkdudeto a certain degree. the (preliminary) clj-kondo type system supports checking required keys in maps for some functions. the other option is to write your own hook for this specific function#2021-10-0916:19pinkfrogCan I suppress “Non-determistic version.” wanring?#2021-10-0916:51borkdudeyou can put #_:clj-kondo/ignore in front of it#2021-10-0916:57pinkfrogCan I do this in the config.edn file?#2021-10-0917:21borkdudeCurrently there is not a specific rule for non deterministic version to let you do this in config. There is only one global deps.edn rule which gives similar output to what the clojure CLI itself spits out #2021-10-0917:45johnIs it possible for a library to export a config.edn (with :lint-as configs) such that consumers of the lib will automatically add in the lib's configs to the application developer's project?#2021-10-0917:58borkdude@john Yes: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-10-0917:59borkdudeIt's almost automatic, you still have to opt into the config as a user in your config#2021-10-0919:17johnSweet! Thanks @borkdude#2021-10-0920:34john@borkdude do you know if Clojure-LSP adds --copy-configs --dependencies , or some equivalent, when it calls clj-kondo? Playing with it in Calva, from a gitpod, I actually see the config getting populated in the project's .clj-kondo/net.clojars.john directory, with the correct :lint-as map in there. But I'm still seeing errors in the actual source files.#2021-10-0920:34johnSo the import is definitely populating the local .clj-kondo dir#2021-10-0920:34borkdudeyes, lsp adds this. but you should opt in to that config in :config-paths yourself, always#2021-10-0920:35borkdude{:config-paths [""]}#2021-10-0920:36johnI put {:config-paths ["clj-kondo/injest"]} in my local config.edn. Maybe I'm exporting the directory structure wrong? I based it off the fulcro repo: https://github.com/johnmn3/injest/tree/main/src/clj-kondo/clj-kondo.exports/net.clojars.john/injest#2021-10-0920:36borkdudeyou should add net.clojars.john/injest#2021-10-0920:36borkdudeif there is a dir like that in your .clj-kondo#2021-10-0920:36johnOkay#2021-10-0920:37johnaaaand that worked#2021-10-0920:39johnPretty awesome! Thanks for figuring all this out#2021-10-1110:57PratikWhat is the right setting for docstrings for multimethods? I have this code which gives misplaced-docstring errors
(defmethod foo :bar
[arg1 arg2]
"doc string"
(prn "Func body"))
If I move the docstring before the arguments the multimethod breaks
#2021-10-1110:57borkdude@pratikgandhi1997 AFAIK docstrings on defmethods aren't supported, only on defmulti#2021-10-1111:02Pratikah, got it, if it was supported then there would be a mix-up between a string dispatch value and the doc strings. Thanks for the quick response!#2021-10-1213:43borkdudeType inference improvements coming up in the next release: https://twitter.com/borkdude/status/1447920160350916608#2021-10-1213:51borkdude(already available on master)#2021-10-1214:06Noah Bogartthat’s cool as hell#2021-10-1215:02pezWhere do I find the definitions of the default linters? I’m specifically interested in Inline def https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#inline-def#2021-10-1215:03borkdudeYou answered your own question ;)#2021-10-1215:04pezIs clj-kondo parsing that markdown file?#2021-10-1215:09pezWhen clj-kondo looks for inline defs it must use some kind of definition, I am thinking.#2021-10-1215:10pezBut I couldn’t find it on a quick scan of the repo, so I am lazy and ask here. 😃#2021-10-1215:11borkdudeThe default level of that linter is :warning the docs say#2021-10-1215:12borkdudeThe default config is in clj_kondo/impl/config.clj#2021-10-1215:12borkdudebut this should not matter, the docs should reflect the truth#2021-10-1215:16pezIt’s still not what I want. 😃 I suck at expressing myself. I’d like to know how clj-kondo goes about determining that something is an inline def. So if I would write a similar linter myself, I could look at the one you’ve done as inspiration.#2021-10-1215:18borkdudeThis is intertwined in the analysis if I remember correctly. If you encounter def when you already entered another def or defn then you know it's "inline"#2021-10-1215:18pezMakes sense. Thanks!#2021-10-1215:19borkdudeWhy are you building your own linter, if I may ask for the context? Just curious#2021-10-1215:24pezI am not. 😃 I just used that as a vehicle to clarify my question. I am suggesting at work that we make the default level for this linter to be :error, and there was worry that we wouldn’t be able to use defs in some contexts that we do today. Now we know that we can just ban them. 😃#2021-10-1215:25borkdudeyou can use #_:clj-kondo/ignore for the rare cases#2021-10-1215:28pezAh, good that you reminded me. Then I can use that on the only case there is in our current code base, before I understand if I can remove it.#2021-10-1215:28borkdudeusually you want intern I think instead of def for "inline" usage#2021-10-1215:29borkdudeor for debugging, I still do it a lot, but then remove it afterwards#2021-10-1215:30pezintern? 👀#2021-10-1215:34borkdude
(interns *ns* 'the-var some-value)
#2021-10-1215:34borkdudeif you want to dynamically define vars#2021-10-1215:47pezWhat’s the difference from def?#2021-10-1215:54borkdudedef is static#2021-10-1215:54borkdudeyou can not have a variable symbol#2021-10-1215:55borkdudealso, def creates the var no matter if you're in a condition or not#2021-10-1215:55borkdudefor example: (when false (def x 1)) still creates the var x but it remains uninitialized#2021-10-1215:59pezOh, interesting! Thanks. Lot’s of TILs for me here. 😃#2021-10-1216:07pezThe worry I mentioned above was actually exemplified with a def in a when. Did you guess that? 😃#2021-10-1216:10borkdudeI did not :)#2021-10-1218:31lreadI’m looking at clj-kondo analysis data while working api-diff PR 🧵#2021-10-1218:32lreadif I understand correctly, clj-kondo analysis data includes clj-kondo hard-coded cherry picked metadata of interest only#2021-10-1218:33lreadfor me, this is probably fine, I am interested in :no-doc which is included.#2021-10-1218:34lreadbut probably an accident that it is included for ns only (not vars).#2021-10-1218:34lread(asking in support of https://github.com/borkdude/api-diff/issues/4)#2021-10-1218:38lreadThere is probably a very good reason that clj-kondo analysis data does not simply include all metadata on var/ns, yeah?#2021-10-1219:55borkdudeHello#2021-10-1219:56borkdudeThere has been work on an issue to ask for more var metadata, but it stalled.#2021-10-1219:58borkdudeWould a function work like {:analysis {:var-meta (fn [m] ...)}} work? Syou can just select the extra metadata you want and this will end up in {:var-definitions [{:name ... :meta ...}]?#2021-10-1220:02borkdude@UE21H2HHD I made a comment here: https://github.com/clj-kondo/clj-kondo/issues/1280 A PR for this is welcome or I'll do it myself since the question has come up a couple of times lately.#2021-10-1220:41lreadYeah, thanks, I think that would work fine.#2021-10-1221:45lreadOh didn’t answer if I am up for this PR. Sure? Maybe? Why not? Yeah, I can give it a go. Unless you’ve already borkduded it!#2021-10-1221:46borkdudenot borkduding on this one so go ahead :)#2021-10-1220:51pinkfrogI am editing a cljc file, and it seem clj-kondo cannot understand cljs correctly. see picture:#2021-10-1220:55borkdude@i write cljs.core/ExceptionInfo instead#2021-10-1220:56borkdudeYou can even leave out cljs.core#2021-10-1221:44leoiacoviniNot sure if its something already known (tried lookin into Github but I didn’t found nothing), but I am having some hard time in clj-kondo recognizing conditional reader macros into metadata annotations. Eg:
(def ^{#
Makes the ns unparsable with the error
missing value for key #
Also using an alternative syntax:
(def ^#?(:clj {:deprecated "deprecation message"})
  my-deprecated-var
  :bla)
Makes the error go away but the metadata doesn’t seem to be preserved for clj-kondo analysis (is does not complain about the var being deprecated)
#2021-10-1221:46borkdudeSo the var is only deprecated in :clj?#2021-10-1221:49leoiacoviniYep#2021-10-1221:51borkdudeWhat about:
(def
  #?(:clj ^{:deprecated "reason"} my-deprecated-var
     :cljs my-deprecated-var)
  :bla)
#2021-10-1221:52borkdudeit's a bit more readable too, I personally think#2021-10-1221:52borkdudebut clj-kondo should probably support the other way too, so feel free to make an issue about it#2021-10-1222:09leoiacoviniIt seems to work with this syntax… However I was facing this from another library I had required in my project, so Ideally would be great to have this fixed without needing to change it in the source. I will open an issue anyway, but thanks for the workaround for now 🙂#2021-10-1222:21borkdudeah that's too bad, yeah, I hope it can get fixed soon#2021-10-1316:22JonRDoes anyone have a suggestion for fixing warnings for unsued bindings in cljs anonymouse fns? Example:
(hooks/use-callback
                             []
                             (util/debounce
                              (fn [ev]
                                (let [{:keys [input-value]} (util/->clj ev)]
                                  (when on-change
                                    (on-change input-value))))
                              debounce-time))
#2021-10-1316:22JonRI get clj-kondo warnings on input-value being unused#2021-10-1316:23JonRI tried using the lsp action resolves as clojure.core/defn but that didn't help. That also seems like it shouldn't be needed so probably not a good plan#2021-10-1316:24JonRSimilarly in this example I get used binding on the second arg, item, but not the first...
(chakra/List
      (->clj (getMenuProps))
      (when isOpen
        (map-indexed
         (fn [i item]
           (chakra/ListItem
            (merge
             {:key i
              :bg (if (= highlightedIndex i)
                    "#bde4ff"
                    "#F7FAFC")
              :borderBottom "solid 1px #E2E8F0"}
             (->clj (getItemProps (->js {:item  (->js item)
                                         :index i
                                         :key   i}))))
            (render-item
             {:hover? (= highlightedIndex i)
              :item   item})))
         items)))
#2021-10-1319:45ericdallothat's odd, you are actually using that input-value variable right?#2021-10-1415:30JonRYup, in both examples the vars are for sure used. It seems like somehow any anonymous fn arg is having this happen in my cljs code...#2021-10-1415:31JonRHere is my config.edn
{:linters {:unresolved-symbol {:exclude [_]}
           :invalid-arity     {:skip-args [mxv.client.react/defrc]}
           :unused-binding    {:exclude-destructured-keys-in-fn-args true
                               :exclude-destructured-as              true}}
 :lint-as {mxv.client.react/defrc clojure.core/defn
           com.wsscode.pathom.connect/defmutation clojure.core/defn}
 :skip-comments true
 :config-paths ["clj-kondo/helix"]}
#2021-10-1416:18ericdallocould you make a simple repro so we can test it?#2021-10-1416:36JonRIt's in a big mono repo so I'll probably need to make a new little project. Will let you know when I have that up. Thanks#2021-10-1412:27Otto Nascarellajust wanted to drop a line and say I’ve been using clj-kondo with cursive, and I love it. thanks ❤️ clojure#2021-10-1413:14borkdudethat's great to hear :) which kind of plugin are you using with cursive, the filewatcher?#2021-10-1413:22Otto Nascarellano, the LSP thingy you reckon file watcher would be better?#2021-10-1413:23borkdudenot at all, just wondering what people are using#2021-10-1415:33ericdallo@U5B8QSSC9 have you tried clojure-lsp with the LSP plugin? :p it uses kondo under the hood as well#2021-10-1415:44Otto NascarellaI tried but it died on me#2021-10-1415:45Otto NascarellaI mean.. on the lsp plugin#2021-10-1415:46Otto NascarellaI’ll try it again, @UKFSJSM38 #2021-10-1415:48ericdalloYeah, I know the intellij LSP plugin has some issues and it's not actively maintained unfortunately :/#2021-10-1415:48ericdalloBut maybe these tips can help: https://clojure-lsp.io/clients/#intellij#2021-10-1517:40fmnoiseHi, does anyone uses https://github.com/cerner/clara-rules here? Any suggestion how to properly lint defrule and defquery?#2021-10-1517:41fmnoiseI use lint-as defn atm, but it doesn't solve it all#2021-10-1517:45borkdudeWithout writing a more sophisticated solution using hooks, you can probably get away with {:lint-as {clara.rules/defsomething clj-kondo.lint-as/catch-all}}#2021-10-1517:45fmnoisethank you @borkdude 🙌#2023-01-0516:38simonkatzVery late to this, but for anyone searching and finding this old thread, I think that should be clj-kondo.lint-as/def-catch-all 🙂#2023-01-0516:43borkdudeyes, sorry#2021-10-1519:25borkdudeFeedback on this one welcome: https://twitter.com/borkdude/status/1449092017573842946#2021-10-1519:50seancorfieldPerhaps my only feedback would be to try to persuade you to make this on by default since it catches beginners out and it doesn't hurt to have (:gen-class) in ns even when you are not AOT'ing and you are using clojure -M -m #2021-10-1519:56borkdudeAh, it won't gen a class when you won't compile right? (EDIT: I meant a .class file on disk)#2021-10-1519:58seancorfieldIt will cause -main to get compiled to static void main(String[]) but that's pretty harmless given that the ns itself will get compiled to a class anyway.#2021-10-1519:59borkdudeRight, but not on disk I guess, only when you AOT (that's what I meant with compile, as in compile , that was ambigious)#2021-10-1520:00borkdudeAnd perhaps there's some CIs that will break because of a false positive, that's why I'm leaning to disabled by default now#2021-10-1520:01seancorfieldIf you use compile, the ns will get compiled to disk -- regardless of the :gen-class -- the only difference is what is done with -main.#2021-10-1520:01borkdudeyes, that's my understanding too.#2021-10-1520:02seancorfieldAll of the *new tools generate projects that have :gen-class in the ns that has -main in it.#2021-10-1520:03seancorfieldIt is far more unusual to not have :gen-class in an ns with -main -- and when someone does that, they can opt out of the linter.#2021-10-1520:03borkdudeWell, bb scripts do have that :-) (although there :gen-class is a no-op)#2021-10-1520:04borkdudeand CLJS but there gen-class doesn't make sense, that's already handled#2021-10-1520:05seancorfieldHow much cljs has -main tho'? And couldn't you just not lint that one in cljs?#2021-10-1520:06borkdudeyes, that's already handled: in CLJS you won't get a warning.#2021-10-1520:07borkdudeI'll do a https://grep.app to see what's out there#2021-10-1520:10borkdudeI'm finding several examples, e.g. this one: https://github.com/metabase/metabase/tree/master/bin/build-drivers For now I'll leave it optional. I think it's better to not cause noise in projects that work perfectly fine without :gen-class and require people to change their code or configs to get a clean clj-kondo CI outcome.#2021-10-1520:14borkdudebtw you can enable it in your local home config and you'll get it for all your projects on your local machine#2021-10-1520:56seancorfield@borkdude Has anything changed recently in project-based configuration of clj-kondo? I'm noticing quite a few of my project-level .clj-kondo/config.edn things are no longer working. Or maybe this is due to some LSP change?#2021-10-1520:57seancorfieldFor example, I have
:missing-docstring {:level :warning}

  :single-key-in {:level :warning}

  :unsorted-required-namespaces {:level :error}}
and none of those linters seem to be in effect now. I have the .clj-kondo folder one level above my clojure folder where all my code lives (in subprojects).
#2021-10-1520:59seancorfieldUgh! Turns out, at some point a .clj-kondo folder got created in the clojure folder and it only had a cache in it -- no settings 😞#2021-10-1520:59borkdude@seancorfield I see the issue. You should put this config in ~/.config/clj-kondo . Previously it probably just worked if you had no .clj-kondo directory in your projects and clj-kondo found that as the closest parent :)#2021-10-1520:59seancorfieldWell, these are project-specific settings, not personal settings.#2021-10-1521:00borkdudeNot sure why those .clj-kondo dirs were created: clj-kondo never does this automatically, but it might be something in #lsp (cc @ericdallo)#2021-10-1521:00seancorfieldThere are a lot of :lint-as settings that are not relevant to any of my other projects -- and I want everyone on the team using clj-kondo to have the same settings/experience.#2021-10-1521:02borkdude@seancorfield There might be a different solution for this. You can have a shared config and refer to that from each project.
repo/clj-kondo/config.edn
repo/project1/.clj-kondo/config.edn: {:config-paths ["../../clj-kondo"]}
#2021-10-1521:03seancorfieldThere's no Clojure elsewhere in the repo -- so I should probably just move it from the root down into the clojure folder, yes?#2021-10-1521:03seancorfield(and there are no more-specific 'kondo configs lower down)#2021-10-1521:04borkdudeThat might work too. But clojure-lsp might create a .clj-kondo directory automatically when it detects a project root by finding a deps.edn or so#2021-10-1521:05borkdudeThis is necessary for it to work properly as it stores analysis data in the .cache directory when it uses clj-kondo for analyzing dependencies#2021-10-1521:06borkdudeSo it might be safer to use :config-paths for shared config between projects#2021-10-1521:07seancorfieldYup, LSP is causing this. I moved the .clj-kondo folder and restarted VS Code and a top-level folder appeared (containing an exported config from test.chuck. I'll do the multiple config.edn dance, as you suggested. Thank you!#2021-10-1521:10borkdude@seancorfield By the same mechanism you can let other people profit from library configuration, if you add config.edn in clj-kondo.exports/your.org/your.lib on the classpath. Then after LSP is done, you will see .clj-kondo/your.org/your.lib with the config in it. All you have to do then it add it to :config-paths (`:config-paths ["http://your.org/your.lib"]`}.#2021-10-1521:12borkdudeWe're keeping a list of examples here of libs that have already done this: https://github.com/clj-kondo/clj-kondo/issues/1383#2021-10-1521:12seancorfieldYeah, I have a ticket open in Expectations to do that.#2021-10-1521:13seancorfieldI seem to recall that 'kondo has already special-cased some stuff for next.jdbc but I should probably set that config up in next.jdbc itself, right?#2021-10-1521:14borkdudeI'd be ok with leaving that in clj-kondo, but for future libs the config mechanism might be better to start with#2021-10-1521:15borkdudeI don't want to break anyone who is relying on built-in stuff#2021-10-1521:16seancorfieldRight, but I'm probably about to add a new macro that would need a 'kondo config so that one, at least, has to be exported from next.jdbc. So I might as well add all the other stuff, to be future-proof.#2021-10-1521:16borkdudeCool, it certainly won't hurt to do so#2021-10-1521:19seancorfield(only with-transaction is currently baked in for next.jdbc -- more is baked in for java.jdbc which is not likely to get updates)#2021-10-1521:19borkdudeMerged the gen-class linter to master, so when Eric bumps kondo in LSP it should be available soon in Calva. I'll probably release a new clj-kondo next week or so (but LSP typically uses the master version).#2021-10-1521:21seancorfieldIn the LSP version I'm using (which is supposed to be "latest" according to VS Code), it has
"clj-kondo-version": "2021.09.25",
#2021-10-1521:21seancorfieldLSP is
"server-version": "2021.09.30-15.28.01",
Does that sound right?
#2021-10-1521:21borkdudeSeems right: https://github.com/clojure-lsp/clojure-lsp/releases#2021-10-1521:22borkdudeI think Calva auto-updates LSP nowadays too#2021-10-1521:59seancorfieldYup. If you have the version set to latest Calva checks on every restart, and downloads a new version if available.#2021-10-1613:50ericdalloNice, I should release soon a new clojure-lsp version with those improvements#2021-10-1813:44lreadBefore I raise an issue, thought I’d check here to see if this is now expected behaviour. I was reviewing clj-kondo dev docs and it has this example:
$ clojure -M:clj-kondo/dev --lint - <<< "(defn foo [x] (if-let [x 1] x x x))"
<stdin>:1:15: error: if-let body requires one or two forms
linting took 73ms, errors: 1, warnings: 0
But if I run this today, I get no warnings:
❯ clojure -M:clj-kondo/dev --lint - <<< "(defn foo [x] (if-let [x 1] x x x))"
linting took 115ms, errors: 0, warnings: 0
Retry with current version of clj-kondo:
❯ clj-kondo --lint - <<< "(defn foo [x] (if-let [x 1] x x x))"
linting took 50ms, errors: 0, warnings: 0
#2021-10-1813:47borkdudeSeems to be a regression#2021-10-1813:47borkdudeIssue welcome. Could be nice to bisect to which clj-kondo version this changed and to see what caused it#2021-10-1813:59borkdude@UE21H2HHD
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "adcfc2dfc6c9d8c9c8ede0effd9f9d9c94"}, :content ("[email protected]")}
#2021-10-1814:00borkdudehttps://github.com/clj-kondo/clj-kondo/compare/v2020.03.20...v2020.04.05#2021-10-1814:02borkdudeperhaps related: https://github.com/clj-kondo/clj-kondo/commit/935d70c7a718f7dc6c449e540f38faf87fd4bd10#2021-10-1814:03lreadRaised the issue: https://github.com/clj-kondo/clj-kondo/issues/1426#2021-10-1814:05borkdudeThanks#2021-10-1814:05lreadMy pleasure#2021-10-1814:11borkdudeI guess it doesn't report it because of this: https://github.com/clojure/clojure/blob/b8132f92f3c3862aa6cdd8a72e4e74802a63f673/src/clj/clojure/core.clj#L1853#2021-10-1814:11borkdudebut now spec does check for it#2021-10-1814:11borkdudeso perhaps core could also change it#2021-10-1814:12borkdudebut I don't think they won't ;)#2021-10-1814:14lreadHuh. Ok interesting.#2021-10-1814:16lreadSo it looks like they allowed for more args to support better assert errors? Or maybe some backward compat since it is called oldform?#2021-10-1814:16borkdudeI think so, but the clojure.spec doen't allow it#2021-10-1814:16borkdudeI posted a message about it in #clojure-dev#2021-10-1814:18borkdudeif-some has the same problem#2021-10-1814:19borkdudeI think we must just must provide some overrides for this#2021-10-1814:19borkdudelet me try to do this#2021-10-1814:24borkdudeyep, special casing works#2021-10-1814:45borkdudeFixed#2021-10-1814:54borkdudeThere is some low hanging fruit to move the override thing to a different place which prevents us from doing this at runtime each time#2021-10-1814:55borkdudebut not high priority, might be fun#2021-10-1814:55borkdudeThe :doc issue is still coming right#2021-10-1814:55borkdudeoh lol, you just posted it#2021-10-1814:57borkdude@UE21H2HHD did you know you can write jet --query ':foo :bar :baz' ? :)#2021-10-1815:43lreadOh you just optimized my jet workflow! jet#2021-10-1815:44borkdudejet !!!#2021-10-1815:49lreadI shall also raise one more issue. Not sure if you’ll want to it fixed. For, what seem to me obscure, signatures of defn and defmacro, there can be an optional 2nd attr-map, which clj-kondo currently ignores.
(defn name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?)
(defmacro name doc-string? attr-map? ([params*] body) + attr-map?)
#2021-10-1815:49borkdudeyou mean in the tail end right?#2021-10-1815:49lreadYeah#2021-10-1815:49borkdudeI don't think anyone uses that#2021-10-1815:49borkdudecan support later#2021-10-1815:49borkdudenot high priority now#2021-10-1815:50lreadI think I won’t bother with an issue then.#2021-10-1815:50lreadI just learned it existed yesterday!#2021-10-1815:50borkdudeactually SCI does support it, let me look up the issue of why I supported it, it was because of some lib#2021-10-1815:51borkdudedang, no context: https://github.com/borkdude/sci/issues/567#2021-10-1815:51lreadCould grasp find usages in the wild?#2021-10-1815:52lreadI would guess it would be very rare, but really don’t know.#2021-10-1815:52borkdudeyes, grasp would find this#2021-10-1815:52borkdudewe can do a grasp#2021-10-1815:55borkdudeactually we can use the clojure core spec for defn here in grasp I think#2021-10-1815:56lreadOk, maybe I’ll raise the issue, and your grasp results can be a good enough reason to close it. Documentation of why we don’t do it, in case it crops up again. Or grasp might tell us we should do it.#2021-10-1816:08borkdudeyeah good idea#2021-10-1816:09borkdudeI'm cooking up a grasp#2021-10-1816:12borkdudeI'm grasping like this:
(ns trailing-meta)

(require
 '[clojure.core.specs.alpha :as specs]
 '[clojure.spec.alpha :as s]
 '[grasp.api :as g])

(s/def ::defn (s/cat :defn #{'defn} :args ::specs/defn-args))
(s/def ::defn-trailing-attr-map (s/and ::defn (fn [conformed]
                                                (->> conformed
                                                     :args :fn-tail second :attr-map))))

(def matches (g/grasp "/Users/borkdude/.m2" ::defn-trailing-attr-map))

;; (prn (s/conform ::defn-trailing-attr-map (first matches)))
(run! (fn [match]
        (print (meta meta) " " match)
        (println)) matches)
#2021-10-1816:12borkdudebut so far no match#2021-10-1816:12lreadCool!#2021-10-1816:14borkdudeah I found something#2021-10-1816:14borkdudebut I made a typo in my program so I didn't see where that was ;)#2021-10-1816:14borkduderunning again#2021-10-1816:16lreadOh. You might curse me. Because it might kind of work already.
clojure -M:clj-kondo/dev --config '{:config-paths ^:replace [] :output {:format :edn :analysis {:var-definitions {:meta true}}}}' \
  --lint - <<< '(defn x ([]) {:doc "attr-map2"})' \
 | jet --query ':analysis :var-definitions first' --pretty
{:fixed-arities #{0},
 :end-row 1,
 :meta {:doc "attr-map2"},
 :name-end-col 8,
 :name-end-row 1,
 :name-row 1,
 :ns user,
 :name x,
 :defined-by clojure.core/defn,
 :filename "<stdin>",
 :col 1,
 :name-col 7,
 :end-col 33,
 :doc "attr-map2",
 :row 1}
Might be just the merge order that is broken when multiple specified? I’ll do more tests.
#2021-10-1816:17borkdudeah, it's omniconf#2021-10-1816:18borkdudeI think that was also the reason I supported it in SCI#2021-10-1816:21lreadOk there is something amiss certainly with :doc derivation from this source but we already have an issue for that. And I think the new :meta analysis might not merge the 2nd attr-map properly if at all. Soo… I do have a small bit of work here.#2021-10-1816:22borkdude> {:line 272, :column 1, :url "jar:file:/Users/borkdude/.m2/repository/com/grammarly/omniconf/0.4.3/omniconf-0.4.3.jar!/omniconf/core.clj"}#2021-10-1816:22lreadThat grasp tool is very cool!#2021-10-1816:22borkdude
{:line 272, :column 1, :url "jar:file:/Users/borkdude/.m2/repository/com/grammarly/omniconf/0.4.3/omniconf-0.4.3.jar!/omniconf/core.clj"}
{:line 312, :column 1, :url "jar:file:/Users/borkdude/.m2/repository/com/grammarly/omniconf/0.4.3/omniconf-0.4.3.jar!/omniconf/core.clj"}
{:line 372, :column 1, :url "jar:file:/Users/borkdude/.m2/repository/com/grammarly/omniconf/0.4.3/omniconf-0.4.3.jar!/omniconf/core.clj"}
{:line 390, :column 1, :url "jar:file:/Users/borkdude/.m2/repository/com/grammarly/omniconf/0.4.3/omniconf-0.4.3.jar!/omniconf/core.clj"}
#2021-10-1816:22borkdudeThat's all I found in my .m2#2021-10-1816:23borkdudeI'll post this info in the SCI issue#2021-10-1816:23borkdudeand in the clj-kondo issue if you make one#2021-10-1816:24lreadYeah, I think I have to do a bit more digging to see what is not working!#2021-10-1816:27lreadYeah… :meta analysis is missing the 2nd attr-map. I can raise for that.#2021-10-1816:28lreadAnd at same time fix meta merge order (which might be fixed by :doc derivation fix).#2021-10-1816:28borkdudethanks#2021-10-1816:41lreadIssue raised: https://github.com/clj-kondo/clj-kondo/issues/1429#2021-10-1820:02lreadOh, I guess we’ll have to address this one too:
❯ clj-kondo --config '{:config-paths ^:replace []}' --lint - <<< '(defn x ([]) ([x] x) {:added "attr-map2"})'
<stdin>:1:22: error: Function arguments should be wrapped in vector.
linting took 8ms, errors: 1, warnings: 0
#2021-10-1907:10jumarI've just found a serious bug in our production code using something like (rseq (map ... This fails because rseq doesn't work on lazy seqs but requires a vector or a sorted map
(rseq (map inc (range 10)))
;;=>
Execution error (ClassCastException) at ...
clojure.lang.LazySeq cannot be cast to clojure.lang.Reversible 
Is this something that clj-kondo could warn against? I understand that this is not a prevalent use case just wondering if that's possible or desirable.
#2021-10-1907:35borkdudeYes, clj-kondo has a type system which can be used for this. We just need to add the types for rseq#2021-10-1907:35borkdudeFeel free to make an issue #2021-10-1909:13borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1432#2021-10-1917:55borkdude#2021-10-2001:22Joshua SuskaloIs there an unused public var linter now? Or did lsp add that?#2021-10-2001:22Joshua Suskalooh yeah, it's being reported as coming from clojure-lsp#2021-10-2005:00didibusThere's https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unused-private-var but its for private vars. With public vars, it's hard to know if its meant to be used by consumers of your library code or not.#2021-10-2005:13seancorfield@didibus If it scans your whole codebase and it's an application, it can detect that. It works really well for us at work -- although it isn't able to spot functions called from our legacy code (of course) nor functions called dynamically.#2021-10-2005:14seancorfield(I'm referring to this https://clojure-lsp.io/settings/#clojure-lspunused-public-var BTW)#2021-10-2005:14didibusYa, it probably relies on clj-kondo's analysis, but I'm pretty sure this issue is why there is no such linter in clj-kondo itself, though borkdude instead created: https://github.com/borkdude/carve for it#2021-10-2012:50ericdalloBecause kondo doesn't know what is your project code, it just know to lint the given files#2021-10-2012:50ericdalloBut it doesn't have the concept of project source paths or classpath of your application#2021-10-2102:44didibusHum, it has its cache, wouldn't that work?#2021-10-2112:51ericdalloThat cache was built by clojure-lsp right?#2021-10-2116:56didibusHum, kinda but not really. See the doc https://github.com/clj-kondo/clj-kondo#project-setup It's a clj-kondo feature for its linters that are cross-namespace. Clojure-lsp might conveniently setup a cache for your project for you, but you can do it even without Clojure-lsp.#2021-10-2005:18didibusI guess it could be an optional linter like some of the other slightly controversial ones#2021-10-2005:23seancorfieldOne person's "controversial" is someone else's "mainstream" 🙂#2021-10-2005:29didibusHaha, true true, but I think some of them you just know they'll be controversial, like missing docstring, or warn when shadowing a global var, or when require is not alphbetically sorted. They just have that quality of being tab vs spaces like in nature 😛#2021-10-2005:41lassemaattaIt's great that with clojure we can avoid that whole tabs vs. spaces debacle and indent our code with commas#2021-10-2005:43didibusGreat idea! Whitespace is overrated. And if I used comma, I could use spacebar as a leader key since I wouldn't need it anymore for coding#2021-10-2005:40seancorfieldTwo of those three are error level linters at work!#2021-10-2013:51mynomotoI do wonder which ones and why :thinking_face: It is always great to get your take on your choices 🙇#2021-10-2016:17seancorfield"missing docstring" (on public vars) and "require is not alphabetically sorted" (in ns).#2021-10-2016:33mynomotoThanks. Do you have a team process to decide what to include on linters?#2021-10-2017:03seancorfieldThere's only two backend devs so there's not really a process but we do discuss this stuff. I just noticed that the missing docstring linter is a warning, not an error. We don't enforce that rule on very small, very obvious functions. And I tend to write more docstrings than my teammate -- because I tend to design my code by writing function signatures and docstrings first, and then writing the code to satisfy that prose. But that does have the disadvantage that the docstrings and code can get out of sync over time (which is another reason we don't require docstrings -- better no docstring than an incorrect one).#2021-10-2017:37mynomotoThanks for the explanation. Knowing your team size also helped put in context other answers from you that I found sort of puzzling in the past related to the absence of conflicts when changing code. 👍#2021-10-2017:52seancorfieldHah, well, we have a lot of different applications/services in the same monorepo and tend to work independently on them so conflicts would be rare even if we scaled up our team, I suspect. We also have very few long-lived branches, have automated CI/CD to our staging environment, and automated deploys to production, which all contributes to reducing conflicts.#2021-10-2017:53seancorfieldCI auto-merges master to every PR when running tests so conflicts against master, at least, would be caught immediately.#2021-10-2009:44mhjortWe noticed that usage of a certain macro is dangerous in our code base. Therefore we made a decision to not use that macro from certain library. Now I am wondering if this rule can be forced with clj-kondo. Is it possible somehow to add project rules like :not-recommended-macros ["my-ns/my-macro-fn"]which will generate a warning?#2021-10-2009:45borkdudeThere is an issue here: https://github.com/clj-kondo/clj-kondo/issues/996 Please upvote and/or comment. Right now you can accomplish a similar effect using the hooks API. Write a hook which emits a warning when the macro is called. After that, just return nil in your hook code to continue linting as usual.#2021-10-2009:46borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-10-2009:47mhjortThanks for the info. I will take a look#2021-10-2009:48borkdudeBtw, if your company is using clj-kondo, would you mind leaving a message here? https://github.com/clj-kondo/clj-kondo/discussions/1397 Then I can list your company on the companies page, if you want.#2021-10-2014:38borkdude@U066DCEM7 I made an example here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#disrecommend-usage-of-function-or-macro#2021-10-2212:18mhjortThanks for the example. Listing our company as a clj-kondo user sounds good. I will double check internally that it is ok and post a message to the discussion.#2021-10-2014:44borkdudeMade some docs around how you can use hooks to disrecommend a call to a function or macro: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#disrecommend-usage-of-function-or-macro#2021-10-2015:04Noah Bogartexcellent, thank you very much#2021-10-2209:07Pratikcan we exclude some type of warnings from all the test files? In our codebase, if we have foo.clj, in the foo_test.clj we are always importing foo with :refer :all and I want to stop the flagging for that#2021-10-2209:10borkdudeYes, you can. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#refer-all#2021-10-2209:10Pratikyes, but I have to manually put all the test files here and update it if I add a new test file, right?#2021-10-2209:11borkdudeno#2021-10-2209:11borkdudeyou put foo there, not your test nss#2021-10-2209:12Pratikthen I have to do the same thing for all the source files, if I add a new source file, I’ll have to mention it in the config.edn, correct?#2021-10-2209:13borkdudecorrect, but you can also just globally turn off this linter. I don't see why you would want to make an exception for tests, just use :refer or an alias#2021-10-2209:13PratikI was looking for something like this option
{:refer-all {:exclude :all-tests}}
#2021-10-2209:14borkdudeI think :refer :all doesn't make tests more readable, but this is my personal opinion.#2021-10-2209:15Pratikyes, it’s just that we are using it across all our codebase, but we might as well switch to aliasing rather than turning it off#2021-10-2209:16borkdudeare you using clj-kondo on the JVM for linting in CI? why is it a problem that these "legacy" issues appear?#2021-10-2209:17Pratikah, so my story is, we were previously using replace in our configs(mistakenly) which was only picking up like 5-6 of the configs, we recently turned it off and added a pre-commit hooks#2021-10-2209:18borkdudePerhaps it's possible to make a .clj-kondo/config.edn in project/test and refer to your base config with :config-paths . I'm not entirely sure if this works correctly with clojure-lsp etc though.#2021-10-2209:20Pratikthis will add extra config file to maintain even if it works, I think we can switch to aliasing or turn off it globally#2021-10-2209:20borkdudecool yeah that would be best#2021-10-2209:20Pratikon a separate thing, is it possible to ignore the full functions from linter warnings?#2021-10-2209:21borkdudeI'm not sure what you mean by this#2021-10-2209:22Pratiksomething like this,
#_clj-kondo{:ignore-function}
(defn foo [] (prom/mlet [...stuff]))
#2021-10-2209:23Pratikwe are using this https://github.com/kumarshantanu/promenade library in some legacy parts of our codebase and I tried to ignore those warnings with :lint-as but couldn’t make it work#2021-10-2209:25Pratikwe only have countable functions written with this library where clj-kondo gives warnings, if we can disable some type of errors for the whole function then it will help my case
#2021-10-2209:26borkdudeah I see. let me take a look at this#2021-10-2209:27borkdudewhy doesn't {:lint-as {promenade.core/mlet clojure.core/let}} work for you?#2021-10-2209:28borkdudepreferably libraries will include clj-kondo config and export it so everyone can use it instead of everyone ignoring it#2021-10-2209:32Pratikhmm, there are other functions like either-as-> and if-mlet which I remember not working when linting as -> and if-let#2021-10-2209:33borkdudethe problem is mostly unresolved symbols?#2021-10-2209:34borkdudeThen you can disable those here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-symbol#2021-10-2209:34borkdudewith :exclude [(promenade.core/mlet)]#2021-10-2209:34borkdudethe author can also provide macroexpansion hooks for clj-kondo to make linting better#2021-10-2209:34borkdudeor as a user you can do this too#2021-10-2209:51Pratikyes, disabling those works#2021-10-2209:52Pratiknot sure about macroexpansion hooks, I can probably create an issue on the repo#2021-10-2209:54borkdudewhat you could do is try to figure those out yourself and then contribute, but this is obviously more work. for now, disabling is the workaround then#2021-10-2209:55Pratik👍#2021-10-2220:53Sam RitchieHey all! quick question about some clj-kondo “errors” I’m seeing in a #sicmutils project; I have a bootstrap-repl! macro that expands to a require form, so I can do the equivalent of use for REPL interaction in both Clojurescript and Clojure. The problem is that clj-kondo doesn’t see these required forms, leading to:#2021-10-2220:54borkdudeYou can write a macro-expansion hook for this#2021-10-2220:54Sam RitchieAnd yes, in a library or production codebase it would be quite poor style to reference vars this way. But this came up when using VSCode to work on a more interactive namespace that I am rendering using #nextjournal’s Clerk project#2021-10-2220:55borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand#2021-10-2220:56Sam Ritchiereading now!#2021-10-2220:57Sam Ritchie@U04V15CAJ if I am writing these for macros in a library, like in this case, is there a good way to share these#2021-10-2220:58Sam Ritchie?#2021-10-2220:58Sam Ritchiefor example I have a bunch of macros in #sicmutils that DO work in SCI already#2021-10-2221:00lread@U017QJZ9M7W have you read https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration?#2021-10-2221:01lreadHere’s an example of clj-kondo exports for rewrite-clj https://github.com/clj-commons/rewrite-clj/blob/main/resources/clj-kondo.exports/rewrite-clj/rewrite-clj/config.edn#2021-10-2221:01Sam Ritchieie I have rewritten them already to work in the SCI context; it would be nice to not have to copy them again over to a config namespace#2021-10-2221:02borkdude@U017QJZ9M7W let's focus on this bootstrap macro for now and not try to optimize everything at once#2021-10-2221:02Sam Ritchie👍#2021-10-2221:02borkdudein general you can't run everything in clj-kondo like you can in SCI, clj-kondo isn't a normal Clojure runtime#2021-10-2221:03borkdudeso I expect you could share some macros but probably not all, like when you use resolve or ns-publics or whatever, you will have to make changes#2021-10-2221:03Sam Ritchie@UE21H2HHD that’s awesome, that for sure answers how to bundle these config options with the sicmutils library.#2021-10-2221:03borkdudealthough we could try to support that use case, it's currently not supported#2021-10-2221:04Sam Ritchie@U04V15CAJ yeah, this particular one does use ns-publics to go grab everything from the sicmutils.env namespace and make it available#2021-10-2221:04borkdudewe do have something else for that now#2021-10-2221:04Sam Ritchieof course I could write something that just manually grabs everything on a library public#2021-10-2221:04borkdudebut this is specific for clj-kondo#2021-10-2221:04borkdudecheck ns-analysis#2021-10-2221:05borkdudebut it's far more reliable if you can pre-generate all your public vars and just let your clj-kondo macro-expansion spit them out for example#2021-10-2221:05borkdudethen you won't rely on the caching mechanism#2021-10-2221:06borkdudeso, you could programmatically create your clj-kondo macroexpansion hook I mean#2021-10-2221:06borkdudeand update it when your library changes, using a script#2021-10-2221:07Sam Ritchieit would work for published versions…. it would have to be a commit hook to be stable for git deps#2021-10-2221:07Sam Ritchieso that any commit, at least to main, would have things up to date#2021-10-2221:07Sam Ritchiethe UX thing I am trying to avoid is#2021-10-2221:07Sam Ritchieof course, where the editor can see a var but clj-kondo can’t#2021-10-2221:08Sam Ritchie(I get why there is a divergence here!)#2021-10-2221:08borkdudeok, you could try to use ns-analysis I guess#2021-10-2221:09borkduderun (ns-analysis 'sicmutils.foo) and print what it returns#2021-10-2221:09borkdudethis will assume that you have already got a cached version of that namespace#2021-10-2221:09borkdudeelse it won't return anything useful#2021-10-2221:09Sam Ritchiedo that inside the macroexpand hook?#2021-10-2221:10borkdudeand you can use that in your macroexpansion yes#2021-10-2221:10Sam Ritchieokay, cool, I will give that a try#2021-10-2221:11borkdudeFor example when I have
(ns app.core)

(defn foo [])
#2021-10-2221:11borkdudeand I stick this in my hook:
(prn (api/ns-analysis 'app.core))
#2021-10-2221:12borkdudeand then lint a file, I will see this in my console:
{:clj {foo {:ns app.core, :name foo, :fixed-arities #{0}}}}
#2021-10-2221:12borkdudeof course you should not print in your expansion "in production", I was just trying to tell you how you could inspect the contents of this stuff#2021-10-2221:43Sam Ritchiejust saw this extra stuff, this is great. Thank you again!#2021-10-2605:43nodenameHi, I haven’t used clj-kondo before but I’d like to use the re-frame analyzer by @roman01la https://gist.github.com/roman01la/c6a2e4db8d74f89789292002794a7142. Is that gist supposed to be a standalone clj program? How would I compile or invoke it?#2021-10-2607:22borkdudeI recommend looking at the repo I just posted by @yannvahalewyn which contains more explanation #2021-10-2617:41nodenameYes, I’m now looking at that repo and unfortunately I know nothing about the cli tools. I’ve tried running it as clj -M scripts/lint.clj but that doesn’t print out the expected output#2021-10-2617:48nodenameObviously I’m doing something wrong because even a (println "Hello") in main doesn’t show up#2021-10-2619:59borkdudelinting the source doesn't execute it#2021-10-2619:59borkdudeperhaps @yannvahalewyn can help?#2021-10-2620:12yannvahalewyn@U04V91K02 I'll add some more explicit steps to the docs!#2021-10-2620:42yannvahalewynI've made the docs much more explicit, have a look and see if that helps you out!#2021-10-2607:22borkdude#2021-10-2617:54nodenameHow do I run this script?#2021-10-2620:02yannvahalewynYou can copy it over in your own repo and just call the main function yourself. It's meant to be copied over and tweaked since lot's of things are hardcoded (such as src paths etc..). Alternatively there's a short section on how to use it from babashka. Not very in depth, could it use some more documentation?#2021-10-2620:04yannvahalewynSince multiple people are asking questions I'm adding some explicit steps to the docs.#2021-10-2620:43yannvahalewynMentioned in the other thread as well but the docs now offer explicit steps on how to get it running!#2021-10-2620:43yannvahalewynMentioned in the other thread as well but the docs now offer explicit steps on how to get it running!#2021-10-2620:49nodename@yannvahalewyn % clj -M -m analyse-re-frame Execution error at clojure.main/main (main.java:40). No namespace: analyse-re-frame found#2021-10-2620:51yannvahalewynHmm let me see, works fine for me#2021-10-2620:52yannvahalewynSome silly things, are you in the correct directory? Did you pull the latest version of the repo? (I renamed that NS in the last commit)#2021-10-2620:53yannvahalewynMake sure you see :paths ... "scripts" in the deps.edn and there is a scripts/analyse_re_frame.clj file.#2021-10-2620:53nodenameYes, I am in the analyse-re-frame-usage-with-clj-kondo directory and pulled. scripts/analyse_re_frame.clj exists#2021-10-2620:54nodenameOh the file says (ns lint) !!#2021-10-2620:55yannvahalewynOh that's my bad, late day and I didn't commit the ns declaration since I was testing the babashka stuff#2021-10-2620:55yannvahalewynI'll push an update but you could replace it yourself and it should work :thumbsup:#2021-10-2620:55nodenameI have received output! Thanks!#2021-10-2620:56yannvahalewynGlad to help!#2021-10-2622:52Joshua SuskaloHey, so the duplicate-map-key linter might need some work. I currently have a monotonically increasing key generation function, kinda like gensym, and calling that function multiple times as keys is guaranteed to be valid, but clj-kondo marks it as duplicates.#2021-10-2622:52Joshua SuskaloIs it intended that calling a no-args function multiple times is treated as an identical key to itself?#2021-10-2622:54Joshua SuskaloOh hmm#2021-10-2622:54Joshua Suskalonever mind#2021-10-2622:55Joshua Suskalothis is unexpected#2021-10-2622:55Joshua SuskaloIt actually is invalid, because the reader breaks.#2021-10-2711:44dazldhi, have a query, and it's probably more relevant here: https://clojurians.slack.com/archives/C0744GXCJ/p1635334848041200 - thanks!#2021-10-2711:45borkdudeIt might be better to re-post the question so it gets logged properly and we can find it back using search engines.#2021-10-2711:48dazldI've figured it out, and shared the solution in the other thread. I'll copy it here too.#2021-10-2711:51borkdudethank you!#2021-10-2711:51borkdudeif the docs need to include this hint, feel free to include it#2021-10-2711:51dazldit would have been helpful, but perhaps this is just my own oversight.#2021-10-2711:52dazldprobably worth waiting to see if another person has the same problem and then considering including it#2021-10-2711:49dazldHey, I had an issue where I couldn't see kondo's linting output in intelliJ with cursive - it turned out that the errors / other output was being hidden by an IDE option - clicking on the warning symbol on the top right opens a panel which allows choosing what to see, and this brought the messages back - just sharing back.#2021-10-2714:51borkdudeHey, I was thinking, re:clojure organizes workshops and if there is any interest in this, I could do a workshop on how to create your own custom clj-kondo hooks.#2021-10-2715:10Noah Bogarti would absolutely be interested in that#2021-10-2715:29Joshua Suskalothat'd be great#2021-10-2715:30borkdude@suskeyhose I think you could already give that workshop instead of me :)#2021-10-2715:31borkdude(which would be fine with me too, haha!)#2021-10-2715:31Joshua SuskaloLol, I'll admit some of my hooks are pretty complex, but I don't quite know if I feel equipped for that level yet.#2021-10-2715:31Joshua SuskaloAlthough I should maybe think about making a workshop for farolero#2021-10-2715:42Joshua Suskaloalthough I did want to get nrepl integration with that before I did a workshop#2021-10-2811:06pmooserIs there a way to do something like ... have an entry in a file that disables kondo in general for that file ?#2021-10-2811:07borkdude@pmooser you can exclude files globally in .clj-kondo/config.edn as well#2021-10-2811:07borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#include-and-exclude-files-from-the-output#2021-10-2811:08pmooserYeah, I was specifically looking for a way to be able to say in a file "this file is ok!" instead of having to mark that in a central location elsewhere.#2021-10-2811:08borkdudethe other option is {:clj-kondo/config {:linters {:unresolved-symbol {:level :off}}}#2021-10-2811:08borkdudein the metadata of your namespace#2021-10-2811:08pmooserI should say thank you, first of all, because this is a pretty neat tool.#2021-10-2811:09pmooserIt actually found 3 errors in my production application that we hadn't run across yet.#2021-10-2811:09pmooserNamespace metadata - perfect! Thank you.#2021-10-2811:09pmooserIs there any way to say "don't warn me about things in comment blocks" ?#2021-10-2811:09borkdudeyes, {:skip-comments true}#2021-10-2811:09pmooserYou are a god among men, borkdude. Thanks.#2021-10-2811:12borkdude@pmooser there is also #_:clj-kondo/ignore that you can apply locally before a form, to ignore warnings#2021-10-2811:20pmooserThe only remaining challenge are a couple macros that the linter gets confused by, and one error that I cannot make sense of because the line number doesn't make sense with the given output. I'm probably doing something to confuse it.#2021-10-2811:21pmooser(to be clear, there's no way for the linter to understand these macros, so that's obviously not a bug)#2021-10-2811:27borkdude@pmooser is the macro syntactically similar to another macro?#2021-10-2811:28borkdudethere are a couple of ways to deal with this in clj-kondo#2021-10-2811:29borkdudeit's best if you could give me some more info / examples on this#2021-10-2811:44pmooser@borkdude The macro isn't similar enough to be able to say "treat it like this" ... It's a macro that has a couple of arguments that are essentially symbol names to bind things to, so when the linter runs it sees me passing (for example) _ as the name of such an argument and it complains that it is undefined.#2021-10-2811:45pmooserIt's very simple:#2021-10-2811:45pmooser
(defmacro run-in-lane
  [lane-id state-name & body]
  `(run-function-in-lane ~lane-id
                         (fn [~state-name]
                           
#2021-10-2811:45borkdude@pmooser you can let clj-kondo expand this macros using: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand#2021-10-2811:46pmooserAhhh very cool, thanks!#2021-10-2811:46pmooserI have one other question ... let me see.#2021-10-2811:48pmooserI'm seeing an error reported as: Unresolved symbol: reagent and that symbol does not occur on the corresponding reported line. Any tips on how I could debug this ?#2021-10-2811:48borkdudeNot sure... if you can make a repro, I could help with this.#2021-10-2811:49pmooserMmm, pretty challenging ... it's in the middle of a mess of deftypes.#2021-10-2811:49pmooserInterestingly the symbol reagent doesn't even occur in the file, except as part of various reagent symbols etc.#2021-10-2811:50pmooserMaybe someday I can learn to set up kondo in such a way that I can just debug the linter myself, instead of wasting your time with it.#2021-10-2811:50borkdudeWell you can check out clj-kondo from git and then use it as a local/repo library and insert some printlns here and there ;)#2021-10-2811:51pmooserPerfect ... I will try to do that.#2021-10-2811:51pmooserThank you again for this cool project.#2021-10-2811:51borkdudeBut I would be happy to join you in a call to take a look, especially if you ended up sponsoring my open source eventually :)#2021-10-2811:51pmooserI'd have to get permission from my corporate overlords to even take advantage of your generous offer, but I appreciate it!#2021-10-2811:52borkdudewhich is not required, just want to communicate that this is a possibility#2021-10-2811:52pmooserYes, totally fair to provide that reminder!#2021-10-2820:29mynomotoWould be ok if I did some triage on the Github issues? Seems like there are things already solved, at least glancing at them.#2021-10-2820:35borkdude@mynomoto very welcome!#2021-10-2820:53pmooser@borkdude It would be nice to be able to distinguish between unused bindings in function arguments versus let blocks, since one of those means you are likely doing unnecessary work, whereas the other might just be a matter of style (I don't always rename all my unused incoming fn args as _ for example).#2021-10-2820:56borkdudeIt depends. When writing a new function, it's often quite useful to see that you've forgotten to use an argument you expected to be necessary#2021-10-2820:56borkdudeBut we can split the linter into multiple if there are more people who want this, sure#2021-10-2820:57borkdudeor add another config option#2021-10-3117:54benedek👋 @borkdude we discussed adding support for re-frame to morpheus (https://github.com/benedekfazekas/morpheus) to visualise re-frame event graphs/deps a while ago. now i forked clj-kondo to add the necessary changes to the analyzer (fork: https://github.com/benedekfazekas/clj-kondo and corresponding branch for morpheus https://github.com/benedekfazekas/morpheus/tree/support-re-frame) it kinda works but not really as it can’t really handle the case when keywords (namespaced or not) used as re-frame event ids are not unique. which is an absolute valid thing to do in re-frame ppl even tend to reuse the keywords as keys in the app-db. so to solve this i started looking into analyze certain re-frame things a bit more in depth (specially reg-sub and reg-event-fx) so i can make sure that referencese to re-frame event ids (keywords) are only considered if they occur at the right place, eg in a (rf/subscribe ...) or in a {:dispatch [:event-id...]). for that i planned to use some re-write clj zippers only i realised they are not available in clj-kondo… just curious about the reasons: perfromance? graalvm don’t like them? suppose you don’t really want them to be part of the inline re-write clj package, right?#2021-10-3118:35borkdude@U0508JT9N Do you mean, zippers in the hooks?#2021-10-3118:52benedeknope, not really. i checked out hooks briefly maybe did not really understand what they were for. i just went for modifing clj-kondo source directly#2021-10-3118:52borkdudethen where did you mean, zippers?#2021-10-3118:52borkdudeyes, clj-kondo itself doesn't use zippers for performance#2021-10-3118:52benedeki mean i clj-kondo I can't really use rewrite-clj zippers can i?#2021-10-3118:52benedekah right#2021-10-3118:52borkdudecorrect#2021-10-3118:53benedekbut if i implement my stuff as a hook i can?#2021-10-3118:56borkdude@U0508JT9N There used to be a zipper API in the hooks: https://github.com/clj-kondo/clj-kondo/commit/40710fe755a10ef0623ae30d224b2d4bea0f5eea#diff-e170b652b1781fe9cad415205220a92f520f94f3c896160a3126e63e5b935694 Which is just the raw Clojure zip namespace which is sufficient in clj-kondo I think since there is no whitespace anymore. But I ended up removing this since I thought nobody was using this. I could add it back though.#2021-10-3119:00borkdude@U0508JT9N you can see here how to do similar stuff with hooks: https://github.com/yannvanhalewyn/analyse-re-frame-usage-with-clj-kondo#2021-10-3119:00borkdudethat project is specifically to detect unused subscriptions, etc#2021-10-3119:02benedekcheers will check it out#2021-10-3119:03borkdude@U0508JT9N the reg-keyword! function is a bit weird: the name is not correct, since it doesn't cause a side effect, it just adds a :reg thing to the node.#2021-10-3119:03borkdudesorry for that, it slipped through in a PR#2021-10-3119:04borkdudeI want to support a more broad :reg like thing, named :context so you can add any key to a node in a hook and it will appear in the analysis. https://github.com/clj-kondo/clj-kondo/issues/1211#2021-10-3119:05borkdudeI think we need this first and then move the reg stuff to use that#2021-10-3119:07borkdudebut looking at your code, it might also be nice to have something like :context {:foo :bar} which is returned from the hook and gets added recursively to all children nodes, which you can then override whenever you return another :context {:foo :baz} or so, so it will work with nested calls#2021-10-3119:07borkdudefeedback welcome#2021-10-3120:42benedekoh somehow my phone did not update the slack thread properly. will check out re-frame related projet you sent the link for and let me think about this a bit more#2021-11-0310:39benedekback on this, and yet an other commit on the top of what I showed you on Monday https://github.com/benedekfazekas/clj-kondo/commit/71644e49976c41f23b063de2c3d63f621421604f — this is kinda my whole proposal/solution only analysing a reg-event-fx body to find :dispatch (and its variations) is missing, subscriptions are simpler. the whole branch https://github.com/benedekfazekas/clj-kondo/commits/analyse-subs-disps — sorry for showing you half baked code, suppose it is just easier to discuss if there is some code, tests to back up what we are talking about. as you can see i am putting this in-subs and in-disp flags in the context, maybe that is what the :context could be used for.#2021-11-0310:40borkdudeCool, I'll take a look at this later today or tomorrow#2021-11-0310:42benedeknw, thx#2021-11-0314:14benedeki think i cracked the last bit of this, so created a PR https://github.com/clj-kondo/clj-kondo/pull/1446 i realise you might want this slightly or entirely differently. i have some unit tests as part of the PR and have not tested this yet with morpheus — plan to do it shortly. let me know what you think whenever you have time, thx!#2021-11-0317:04borkdudeThanks, I'll take a look hopefully tomorrow, busy day :)#2021-11-0512:00benedeknot to hurry you, just reporting really some tests on the re-frame example todo app with morpheus and this PR showed some encouraging results. I do need to add a bit to the PR for inject-cofx calls tho it seems. will test further wonder if this PR would enable a find references and unusued re-frame things as well in lsp#2021-11-0512:14borkdudeI have started looking into the PR. I would like to keep things a bit general instead of building in bespoke things for re-frame, so it will work for other libraries too. I'll be coming back with feedback on this. Perhaps the :context issue should be solved as a first step towards this.#2021-11-0512:14borkdudeI think after your PR has been merged, lsp can benefit from this too#2021-11-0109:35BenjaminHow do I tell clj-kondo that my file .cljc file is clojure? (I'm assuming it treats it as clojurescript based on the extension)#2021-11-0109:40borkdude@benjamin.schwerdtner I'm still figuring out the best way to deal with this. I'm assuming you're writing a babashka file with a reader conditional? Right now this is supported in config.edn: {:cljc {:features [:clj]}} (but still officially undocumented): it will only look at the :clj branches of the .cljc files#2021-11-0109:43Benjaminah you are right that is the initial use case. You made me realize I don't need the c because it's only clojure now 😛#2021-11-0121:43winsomeI'd like to generate a graph of my namespace dependencies - I see that there's a clj -m clj-kondo.tools.namespace-graph src command documented under Analysis Data > Namespace graph, but it looks like it's trying to read a png file? > Execution error (FileNotFoundException) at http://java.io.FileInputStream/open0 (FileInputStream.java:-2). > clj-kondo.tools.namespace-graph (No such file or directory)#2021-11-2516:40borkdudeI looked into it and on my system it worked. I think the issue is that you haven't installed graphviz.#2021-11-0121:47borkdude@winsome Feel free to post an issue and I'll look later this week. There are some better tools that use clj-kondo analysis to show namespace or even function dependencies. One of them is called morpheus by @benedek https://github.com/benedekfazekas/morpheus#2021-11-0121:48benedekthe ns deps one is https://github.com/SevereOverfl0w/vizns#2021-11-0121:48benedekalso powered by kondo#2021-11-0121:56winsomeAlright, vizns worked! It's not pretty but now I've got my graph. I think I'll play more with morpheus too#2021-11-0212:09Chris McCormickHello, I have {:lint-as {promesa.core/let clojure.core/let}} in .clj-kondo/config.edn and I am seeing Unresolved symbol: a for (p/let [a 12]) - is this expected behaviour?#2021-11-0212:09borkdudeCan you point me to the repo?#2021-11-0212:16Chris McCormickit happens in the p/let at the bottom of this: https://github.com/chr15m/create-sitefox-nbb/blob/main/template/server.cljs the clj-kondo config is in that same dir.#2021-11-0212:19borkdudeCan't reproduce. Can you execute clj-kondo --lint server.cljs on the command line and see what it produces? Are you sure this is coming from clj-kondo and not some other linter?#2021-11-0212:20Chris McCormickOh maybe you're right, maybe my setup is wrong. I'll investigate, thanks.#2021-11-0212:22Chris McCormick
/home/chrism/bin/clj-kondo --lint - < server.cljs 
<stdin>:32:11: error: Unresolved symbol: self
If I directly run it it fails to find the file, even though it's definitely there:
$ /home/chrism/bin/clj-kondo --lint server.cljs 
server.cljs:0:0: error: file does not exist
linting took 31ms, errors: 1, warnings: 0
I installed from the AppImage by copying it into ~/bin which is on my path. :thinking_face:
#2021-11-0212:23borkdudeare you inside the template directory?#2021-11-0212:23borkdudefile does not exist indicative of ... the file does not exist#2021-11-0212:24Chris McCormick
$ pwd
/home/chrism/dev/create-sitefox-nbb/template
$ clj-kondo --lint server.cljs
server.cljs:0:0: error: file does not exist
linting took 31ms, errors: 1, warnings: 0
$ ls -alh server.cljs 
-rw-rw-r-- 1 chrism chrism 1.3K Oct 31 13:08 server.cljs
#2021-11-0212:25Chris McCormickcould this be a strange bug with the appimage version not resolving paths correctly?#2021-11-0212:25Chris McCormickmaybe i shouldn't be doing this?
$ ls -alh ~/bin/clj-kondo 
lrwxrwxrwx 1 chrism chrism 75 Oct 27 13:04 /home/chrism/bin/clj-kondo -> contrib/clj-kondo-2021.09.25-lp151.73.1.Build73.1.glibc2.14-x86_64.AppImage
#2021-11-0212:25borkdudeI don't know what appimage is. Just install it from github releases using the installer script#2021-11-0212:25Chris McCormickoh ok, its linked from the clj-kondo docs#2021-11-0212:26Chris McCormick> There is also an https://download.opensuse.org/repositories/home:/zilti:/clojure/AppImage/clj-kondo-latest-x86_64.AppImage. If you use the AppImage, simply save the file as "clj-kondo" and make it executable. It is fully self-contained - without the overhead that comes with Docker!#2021-11-0212:27borkdudeI guess I'll just comment that out then since it doesn't seem to work#2021-11-0212:28Chris McCormickOk using the installer with --dir /home/chrism/bin has fixed the issue. Sorry for the noise!#2021-11-0212:28Chris McCormickThanks for your hlep.#2021-11-0212:29borkdudeAdded by zilti: https://github.com/clj-kondo/clj-kondo/commit/fcbab419ced4abb538ae2715d7db5b560aaff488 I'll contact him. Thank you.#2021-11-0219:00Joshua SuskaloHey @borkdude is there a good way for me to specify in clj-kondo hooks that a value is bound, but we don't know to what? I can't use an anonymous function because that causes incorrect behavior wr/t recur linting, and if I bind the values to nil in a let block then I get type errors in the code inside it.#2021-11-0220:22Joshua SuskaloThe solution I ended up coming up with is to emit a let block that looks like this:
(let [some-binding (clojure.core/first nil)]
  (+ some-binding 2))
The problem before was that some-binding was giving me warnings about being nil and passed to +, so more or less I wanted to emit an untyped binding form.
#2021-11-0220:22Joshua SuskaloI don't really consider this ideal, but it's good enough I guess#2021-11-0220:58borkdude@suskeyhose bind to a number perhaps? or does that also cause type errors for other situations?#2021-11-0220:58Joshua Suskaloyea#2021-11-0221:00borkdudeyeah on the first or second?#2021-11-0221:03Joshua Suskaloit also causes type errors#2021-11-0221:03Joshua Suskalofor anything that like needs a sequence#2021-11-0221:03Joshua SuskaloThe hook is controlling what value is bound#2021-11-0221:03Joshua Suskaloit's not in my code#2021-11-0221:03Joshua Suskalopractically speaking it's like making a function call, but there's no actual function call boundary and recur goes back to an outer recur point#2021-11-0221:06borkdudeCan you give some examples of how this looks?#2021-11-0221:07Joshua Suskalo
(loop []
  (restart-case
      (far/error ::some-error)
    (::far/use-value [v]
      (recur))))
This recur will recur back to loop, but the ::far/use-value clause is called like a function (in some handler on a different part of the stack)
#2021-11-0221:09borkdudeso this is a macro which expands the keyword ::far/use-value into something like fn?#2021-11-0221:09borkdudecan you show what it expands into? less guesswork for me#2021-11-0221:09Joshua Suskaloit's like fn, but in reality it's like getting the values out of an exception and destructing them inside a let statement#2021-11-0221:09Joshua Suskalothe expansion is.... complex#2021-11-0221:10borkdudethen an expansion that only illustrates the idea but dumbed down?#2021-11-0221:11Joshua Suskalo
(loop []
  (let [[v] (try (far/error ::some-error)
                 (catch Signal s (.-args s))]
    (recur)))
#2021-11-0221:11Joshua Suskalothat's more or less what it ends up doing, but very simplified#2021-11-0221:12borkdudeI think you could just expand into something like
(let [{:keys [v] {}] ..)
clj-kondo isn't currently looking at the contents of the map literal to deduce that v is nil
#2021-11-0221:12Joshua Suskalookay, I can try that.#2021-11-0221:12Joshua Suskalothanks!#2021-11-0221:26borkdude@suskeyhose off topic question: did you get anything working in graalvm jdk 17 with panama + native image?#2021-11-0221:26borkdudeI'm wondering if I should upgrade to jdk 11 21.3.0 or jdk 17 21.3.0#2021-11-0314:32Joshua SuskaloI had some other stuff that took a lot of my free time, so I haven't had the chance yet.#2021-11-0317:58Otto Nascarellahiya! I was wondering if there’s a way to lint namespace aliasing…. to avoid too short names, for example#2021-11-0318:01wilkerlucioI think there inst one for small, but there is “consistent aliasing” where you can set a fixed alias per namespace, and it fails if someone tries to make it different#2021-11-0318:34borkdude@U5B8QSSC9 You can use the clj-kondo analysis to access all namespace aliases and do whatever you want with it#2021-11-0318:34borkdudeBut currently there is no specific linter for the shortness of aliases#2021-11-0318:36Otto Nascarellathanks for replying, guys will look into it#2021-11-0318:36borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#2021-11-0408:33kommenis feasible to get and an “unused binding” warning for x here?
(defprotocol Foo
  (y [_ bar baz]))

(defn f []
  (reify Foo
    (y [_ x z]
      (println z))))

(y (f) "a" "b")
#2021-11-0409:07borkdudeyes: https://github.com/clj-kondo/clj-kondo/issues/1333#2021-11-0409:07kommenthanks!#2021-11-0409:07borkdudeI'll make a similar issue for defprotocol and reify#2021-11-0409:09borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1447#2021-11-0409:11kommen🙇#2021-11-0417:29Noah BogartI’m using the mongodb library monger, and it defines a bunch of mongo-specific query operators, such as $or. These are in the namespace monger.operators , all defined with a macro: https://github.com/michaelklishin/monger/blob/master/src/clojure/monger/operators.clj#2021-11-0417:29Noah Bogartbecause of this, usage of the operators in my code give unresolve-var errors: [monger.operators :refer [$or]]#2021-11-0417:30Noah Bogartany ideas for a solution here?#2021-11-0417:31borkdude@nbtheduke {:lint-as {monger.operators clojure.core/def}} and then re-lint your dependency#2021-11-0417:31borkdudeoptimally that config should be exported as part of the library itself#2021-11-0417:31Noah Bogartoh wow, that’s easy#2021-11-0511:02kirill.salykinhi Can clj-kondo lint on unused fns? (eg with zero refs)#2021-11-0511:03borkdude@kirill.salykin you can do this in two ways: • Use https://github.com/borkdude/carve as a tool to get a report for unused functions • Use #lsp in your editor to see how many references there are for a function (in emacs lsp it's called lens mode)#2021-11-0511:42ericdalloActually you don't need lens enabled, clojure-lsp will return a diagnostic saying that function is unused public var#2021-11-0512:00kirill.salykinI was more in running it on CI already have it in my emacs 🙂#2021-11-0512:00kirill.salykincarve seems exactly what i needed, thanks!#2021-11-0512:09ericdallofor CI you can check this as well: https://clojure-lsp.io/api/#ci#2021-11-0512:10kirill.salykinwow, it is brilliant! thanks a lot#2021-11-0520:25agSo the question I mistakenly posted in #babashka @borkdude you say, use macroexpand hook instead of analyze-call, but I can't figure out, say for example, how do I write a hook for compojure.api things? e.g.:
(context "/api" []
      :tags ["api"]

      (GET "/plus" []
        :return {:result Long}
        :query-params [x :- Long, y :- Long]
        :summary "adds two numbers together"
        (ok {:result (+ x y)}))

      (POST "/echo" []
        :return Pizza
        :body [pizza Pizza]
        :summary "echoes a Pizza"
        (ok pizza)))))
How do I get pizza and x, and y to "be resolved"?
#2021-11-0520:28borkdudeThere are various ways to deal with this. From easy + less precise to hard/more work + more precise errors: 1. Suppress unresolved symbols in compojure.api/context or compojure.api/GET etc, using the configuration. https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-symbol#2021-11-0520:28borkdude2. :lint-as can be used if there is a function/macro that behaves syntactically the same (but that doesn't seem to be applicable here)#2021-11-0520:29borkdude3. use :macroexpand hook to write a macro to transform the code into simpler code that clj-kondo can understand. it does not have to transform into code that "works", just into expressions that clj-kondo will lint and make sense for linting. The macro does not have to correspond to the real macro.#2021-11-0520:30borkdude4. use :analyze-call hook. Similar to 3. but this gives you more precise locations for errors.#2021-11-0520:30borkdudeSo let's say if we shoot for 3, can you come up with a macro that receives the above expression and turns it into something that doesn't have special syntax?#2021-11-0520:31borkdudeyou can write macros separately for context, GET, POST, etc#2021-11-0520:31borkdudelet's focus only on GET for now#2021-11-0520:32agI've tried 1 and 2 and it didn't work perfectly for me, because then things used within the POST block would not be recognized as used and kondo flags them as unused references. macro I tried, but couldn't figure it out (forgot exact reasons) thought I'm gonna need analyze-call for that, but that turned out to be even more tangled#2021-11-0520:33agI'll give a try to :macroexpand hook again#2021-11-0520:33borkdudeI think 1 should work without any false positives though#2021-11-0520:34borkdude
(ns foo
  {:clj-kondo/config '{:linters {:unresolved-symbol {:exclude [(compojure.api/GET)]}}}}
  (:require [compojure.api :refer [GET]]))

(GET "/plus" []
     :return {:result Long}
     :query-params [x :- Long, y :- Long]
     :summary "adds two numbers together"
     (ok {:result (+ x y)}))
#2021-11-0520:34borkdudeThis works without errors#2021-11-0520:35borkdudeI don't know the exact namespace for GET, this is just an example#2021-11-0520:35borkdudeAlso when you type:
(let [foo 3]
  (GET "/plus" []
       :return {:result Long}
       :query-params [x :- Long, y :- Long]
       :summary "adds two numbers together"
       (ok {:result (+ x y foo)})))
then foo isn't marked as unused
#2021-11-0520:36borkdudewith that config#2021-11-0520:37borkdudeare you using the :refer :all like in their README? this could cause problems as clj-kondo has to do guesswork where stuff is coming from#2021-11-0520:37agRight. okay. I'll keep playing with this. Sorry for being fuzzy on that. I'm space out a bit, because my last attempt was a couple of weeks ago. And cleaning up things with kondo in a huge project is not "a real work", but I'm doing it as a "side-project"#2021-11-0520:37borkdudesure, no problem#2021-11-0520:38borkdudeJust come back with one isolated small piece of code where 1 doesn't work for you and I'm confident we can fix it#2021-11-0520:39agAlright! I guess I was overly excited and wanted to learn how to make custom hooks with :analyze-call, even though might be an overkill for this task 🙂#2021-11-0520:39borkdudewe can also do that. I think 3 is easier to get started with#2021-11-0520:44borkdude@U0G75ARHC I think this could be a good start for a macro for GET :
(defmacro GET [path args & {:as opts}]
  [path args (update opts :query-params
                     (fn [params]
                       (list 'fn (vec (remove  #{':-} params)))))])
#2021-11-0520:44borkdude
(macroexpand '(GET "/plus" []
                   :return {:result Long}
                   :query-params [x :- Long, y :- Long]
                   :summary "adds two numbers together"))
#2021-11-0520:44borkdude
["/plus" [] {:return {:result Long}, :query-params (fn [x Long y Long]), :summary "adds two numbers together"}]
#2021-11-0520:45borkdudeit's not perfect yet, but I hope you see the idea#2021-11-0520:46borkdudeso that last expression is something which clj-kondo can understand#2021-11-0520:46borkdudeyou'll have to wrap the body of the GET into the function and then it will also understand the usages within the body#2021-11-0521:37agThank you. I'll try this. Really appreciate your help. I think this gives me enough food for thought. I'm sure I'll have to come back again and ask some more questions.#2021-11-0522:18agOkay, now I remember why I wanted analyze-call.#2021-11-0522:23agSo, I have something like this:
(context "/:id" []
  :query-params [{wait_for :- s/Bool}]
  :path-params [id :- s/Str]
  (PATCH "/" []
    ;; ... id an wait_for are used somewhere here
Using :unresolved-symbol {:exclude would then ignore the actual errors within. So for example I rename id to foo - instead of telling me that foo is unused, it would just ignore that entire block. If I use :hooks :macroexpand, then (even if I do it right) if there's something wrong, it will show the errors all the way at the beginning of the block. These blocks can get too long, it will be annoying to try to find a misplaced var(s).
#2021-11-0522:26borkdudeYes, 1) this is a trade-off, you will ignore all false positives, but won't get additional errors. 2) yes, this is also a trade-off of :macroexpand. if you want precise locations you should make this an :analyze-callhook. The implementation is similar to your macro but is based on nodes rather than s-expressions.#2021-11-0522:26borkdudeso it's gradually more work but also getting better feedback#2021-11-0522:26borkdudeafk now, will respond tomorrow#2021-11-0609:12Adam HelinsWhatever file I lint in this CLJS project, I get this same error:
src/salus/client/util.cljc:0:0: error: Can't parse src/salus/client/util.cljc, Configuration error. Expected fully qualified symbol, got: salus.client.js.citizen.domain.language
Now, salus.client.js.citizen.domain.language is a real namespace, but I can't figure out what's really wrong
#2021-11-0609:19borkdude@adam678 this error is about a misconfig in your .clj-kondo config.edn#2021-11-0609:21borkdudeYou’re expected to put a fully qualified symbol somewhere where you’ve only used an unqualified one #2021-11-0609:24Adam HelinsAh right, someone hard a brain fart it seems, it shouldn't even be in there Thanks!#2021-11-0615:45lilactownI am feeling a bit dumb. I'm trying to setup https://github.com/lilactown/helix so that consuming projects will be able to automatically get clj-kondo config for its macros. I haven't been able to get it to work yet#2021-11-0615:45lilactownin my consuming project, I can see the config file on the classpath:
user=> (slurp (io/resource "clj-kondo.exports/lilactown/helix/config.edn"))
"{:lint-as {helix.core/defnc clojure.core/defn\n           helix.core/defhook clojure.core/defn\n           helix.core/fnc clojure.core/fn}}\n"
#2021-11-0615:46lilactownis lilactown/helix right? or does it need to be just helix#2021-11-0615:46lilactownsince the require is helix.core helix.dom etc.#2021-11-0615:46borkdude@lilactown this is correct. but you need to lint your classpath with --copy-configs#2021-11-0615:46borkdudeand then clj-kondo will copy the config to the .clj-kondo directory if that directory exists#2021-11-0615:47borkdudeand then you need to add it to your :config-paths in your .clj-kondo/config.edn#2021-11-0615:47lilactownI see. I thought I just needed to run the command to copy the config and nothing more#2021-11-0615:47borkdudeno need to feel dumb, it's not so obvious with several steps that you need to do#2021-11-0615:47lilactownit sounds like there's some manual config as well#2021-11-0615:48borkdudecorrect, this is to prevent problems with config that people don't want in their project for some reason, safety, etc#2021-11-0615:48borkdudeyou should explicitly opt into the configuration
#2021-11-0615:50lilactownwhaddaya know it works 🙂 ty for help!#2021-11-0615:50borkdude:-D#2021-11-0615:51lilactownalso glad that I did the right thing in my lib for everyone else#2021-11-0616:09lilactownin an app or service, do people commit just their .clj-kondo/config.edn and let individual devs run the copy command? or do people commit the copied configs from libs too?#2021-11-0616:10borkdude@lilactown I'd say commit in the entire directory except .cache so your team mates have the exact same config#2021-11-0616:11borkdudeand this will work in CI then too#2021-11-0616:12lilactownI'll do that then#2021-11-0720:54seancorfieldI've just added clj-kondo.exports to next.jdbc -- can someone sanity check that I did it correctly? https://github.com/seancorfield/next-jdbc/commit/99f814bb258a8e11924f6cb9f72274daa04647b8 -- I know that the with-transaction macro is already baked into clj-kondo but this will pave the way for any future macros added to next.jdbc. I am about to move on to Expectations next.#2021-11-0721:06borkdude@seancorfield That looks good. Note that you don't have to duplicate your config. You can refer to your config in the exported directory by adding it to :config-paths in .clj-kondo/config.edn#2021-11-0721:07borkdude
:config-paths ["resources/clj-kondo.exports/com.github.seancorfield/next.jdbc"]
#2021-11-0721:09borkdudeNote that namespaces inside the exported directory should also follow an org/lib structure. Instead of hooks.next-jdbc choose seancorfield.next-jdbc for example, this will ensure that you won't get conflicts with anyone else that writes hooks for this library#2021-11-0721:17seancorfieldAh, I thought the hooks were already "local" to that tree. My bad. As for the "copy", that's what happens when I run clj-kondo --copy-configs --dependencies --lint "$(clojure -Spath)" on the project so I can work within it.#2021-11-0721:20seancorfield(and that seems to be what the documentation suggests you should do, BTW)#2021-11-0721:24seancorfield(updated the next-jdbc hook to .github.seancorfield.next-jdbc)#2021-11-0721:35borkdudeCool. The hooks part isn't really necessary, but doesn't hurt either.#2021-11-0721:37borkdudeClojure-LSP automatically lints the code with those settings so everyone who uses clojure-lsp will receive those configs in their .clj-kondo directory and then can opt in via :config-paths#2021-11-0721:47seancorfieldIs the expectation that a project should .gitignore everything in the .clj-kondo folder except config.edn? I'm already ignoring .clj-kondo/.cache in most projects...#2021-11-0721:57borkdude@seancorfield No, just .cache . The config (also imported configs) can be checked in so linting works the same for everyone who runs clj-kondo on it, in CI, etc.#2021-11-0722:08seancorfieldOK. And, just to be clear, that means the "duplicated" config since clj-kondo copies it when you run that command (that I showed above).#2021-11-0722:17borkdudeYou can gitignore that part of your .clj-kondo for your specific project, since its already in your source control, especially when you configure it via :config-paths#2021-11-0722:18borkdudeFor other users of your library I recommend checking in into their source control in the .clj-kondo dir#2021-11-0722:24seancorfieldOK, thanks. That helps clarify things -- but isn't obvious from the docs.#2021-11-0722:46borkdudeFeel free to propose/PR some changes to the docs#2021-11-0723:00seancorfieldI read it over a few more times and see if I have any suggestions...#2021-11-0909:01Chris McCormick#2021-11-0915:02mpenetis there a way to exclude an unused binding by name, regardless of ns (typically "this")#2021-11-0915:02mpenetI want to avoid replacing by this or everywhere#2021-11-0915:02mpenetand create giant diffs#2021-11-0915:02mpenet(so via clj-kondo config would be better)#2021-11-0915:07borkdude@mpenet currently not. this is all the config that is possible currently: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unused-binding If this is important for passing CI or git post-commit hooks, then you can turn that linter off for now perhaps using an extra configuration that you don't use in your editor. Feel free to create an issue about this.#2021-11-0915:11mpenetI imagine that could be done generically for defrecord/reify/deftype etc bodies#2021-11-0915:11mpenet:ignore-self-referencing-arg or something#2021-11-0915:15borkdudeyes#2021-11-0915:15borkdudeI agree#2021-11-0917:57FiVoHey, I sometimes switch branches. Some namespace api changes and even after having evaled calling site as well as the changed ns, I am still stuck with unresolved var or some changed arity issue. I am using your flycheck integration. Is this a known issue?#2021-11-0918:00Joshua Suskalothe easiest way to deal with this is to delete the .clj-kondo/.cache directory#2021-11-0918:00Joshua SuskaloYou could configure magit to do that automatically on checkout#2021-11-0918:07borkdudePerhaps clojure-lsp will also fix that automatically by reindexing changed files (cc @ericdallo)#2021-11-0918:10FiVook. So the current solution is the magit checkout hook?#2021-11-0918:11borkdudeor run clj-kondo --lint src on checkout#2021-11-0918:11borkdudeto update changed sources#2021-11-0918:12borkdudewhich is probably better than throwing away your entire cache#2021-11-0919:51ericdallothis is a known bug on clojure-lsp side, we are currently ignoring didChangeWatchedFiles notifications from client which happens when user change the files outside the editor (using git for example)#2021-11-0919:52ericdallo@borkdude that's related with my clj-kondo feature request of allowing to pass multiple input texts during lint I mentioned some weeks ago, I need to open the issue yet 😔#2021-11-0919:54ericdallofrom out DM: I found something to improve clojure-lsp performance during content changes that should fix some issues and I'd like to include not on the release of this week but on the next, but I found I can't make it work with current clj-kondo api the issue is that ATM clojure-lsp calls clj-kondo in 2 possible ways: • when analyzing external classpath or project sourcepaths, calling clj-kondo to scan a list of filenames • when any code is changed, calling clj-kondo with `:lint ["-"]` passing the buffer text as stdin I'm refactoring and improving the later, if someone change a git branch, or for some reason change multiple files multiple times, clojure-lsp call N times clj-kondo, making cpu go crazy obviously, I made some changes that will debounce and group these changes in a single clj-kondo call, but then I just found there is no way to pass multiple "texts" to clj-kondo 😅 I'd need something like:
:filenames ["a.clj", "b.clj" "c.clj"]
:lint ["text a", "text b", "text c"]
or wherever api you think it'd be the best, WDYT? Does that makes sense for you? borkdude  can you explain why you need to pass code + file names which aren't actually files? ericdallo  [9:43 AM] Because the code is not necessarily saved on disk, so we have only the text code and we need to know which URI that text was related borkdude  [9:43 AM] but where does this code come from? I don't understand the use case and would like to know more about it ericdallo  [9:44 AM] It's the code from the editor that was changed for example because of a git branch change borkdude  [9:45 AM] but why can't you just pass the changed file names in this case? ericdallo  [9:46 AM] Because they are not necessarily persisted on disk :/ [9:46 AM] They could be only on user buffer borkdude  [9:46 AM] I see yeah [9:47 AM] ok, can you make an issue? I'll think a little bit more about this. Is this blocking you?
#2021-11-0919:54ericdalloI'll try to create the issue later today#2021-11-0920:57borkdudeYes, please do :)#2021-11-0920:57borkdudeIt will also solve an issue I had recently. I worked around it by writing the inputs to temporary files ;)#2021-11-0920:58ericdalloI see! alright, I should open the issue tonight, thanks!#2021-11-1214:17ericdalloFinally: https://github.com/clj-kondo/clj-kondo/issues/1456#2021-11-1214:18borkdudeAh, the relief of tension...!#2021-11-1214:24ericdallohahah, sorry, kind of a crazy week 😅#2021-11-1214:25borkdudeNo problem ;)#2021-11-1003:23adc17Hey folks, I'm trying to write a hook (https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md). Right now I'm doing stuff like this: (prn (api/sexpr node)) and just running the linter each time to log output. It would be great if instead I could generate a value that I could interactively def in my repl, and then pass it to my custom hook to iterate more rapidly. Does anyone know if this is doable?#2021-11-1009:41borkdude@alexchalk17 Please post an issue about it (if there isn't already one)#2021-11-1114:01joost-diepenmaathi everybody! is there a way to write custom per-project linters with clj-kondo? Would be a good way to try out new linters and to enforce specific styles#2021-11-1114:02joost-diepenmaatany pointers how to go about writing new linters in the clj-kondo codebase would be helpful too#2021-11-1114:18borkdude@joost-diepenmaat yes, this is possible using hooks (or specific config for your project-specific functions). https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-11-1114:22borkdude@joost-diepenmaat You can see several examples of this of libraries that export their custom hooks: https://github.com/clj-kondo/clj-kondo/issues/1383#2021-11-1114:35joost-diepenmaatthanks @borkdude. do hooks allow me to add additional linters to def* forms? I would like to do additional checks on docstrings, similar to emacs’ checkdoc function for elisp.#2021-11-1114:35joost-diepenmaatso I won’t be dealing with new macro’s, but actually adding checks to existing ones#2021-11-1114:37borkdudeyes, just write the hook for the core macro and then don't return a new node, just emit warnings using reg-finding!#2021-11-1114:37joost-diepenmaatI’ll give it a shot. thanks!#2021-11-1117:49mynomotoCan I ignore a specific expression on "Redundant expression"? My usecase is I'm using https://github.com/hyperfiddle/rcf and random := have meaning on the tests expression.#2021-11-1117:50mynomotoThe default config only has a level config for that linter.#2021-11-1117:51borkdude@mynomoto You can ignore any warning by prepending the form with #_:clj-kondo/ignore#2021-11-1118:06mynomotoYeah, the problem is that this would make the minimal syntax not so minimal or I would have no linting on the whole form. I think I will disable this linter on the namespace configuration.#2021-11-1119:03borkdude@mynomoto or you can write a hook for this macro#2021-11-1119:28mynomotoYeah, I will try to do that on the project. Is there a how to write hooks guide?#2021-11-1119:28borkdudehttps://clojurians.slack.com/archives/CHY97NXE2/p1636653310182500#2021-11-1119:30borkdudeI think it can be a :analyze-call hook which rewrites := to (= x y)#2021-11-1119:30mynomotoOk, thanks!#2021-11-1119:30borkdudewhat's the reason for this syntax instead of (is (= 1 2 3))?#2021-11-1119:49mynomotoI like my syntax really regular but after spending some time with this library I got to like this choice of syntax. And it wins hands down against comment blocks that what this is replacing in the codebase.#2021-11-1119:52borkdudeAlright :)#2021-11-1119:52borkdudewhat's wrong with just (is (= 1 2 3))?#2021-11-1119:54borkdudeI changed the phrasing of my earlier comment#2021-11-1120:16mynomotoYou mean inside the tests or inside a deftest?#2021-11-1120:17mynomotoInside tests would not report an error, inside a deftest it would not be elided on prod.#2021-11-1120:17borkdudeI see#2021-11-1120:18mynomotoI like the tradeoff, but I'm always open to suggestions or finding new options.#2021-11-1120:18borkdudeyes, there are always trade-offs#2021-11-1117:52borkdudeinteresting syntax choice...#2021-11-1118:07mynomotoIf someone does another version of this lib using a more regular syntax I would go for it. 😉#2021-11-1117:55otfromI'm trying to write a hook for tech.v3.datatype.export-symbols I've got a function that is being called by the hook and it is getting the right data (I think). I think I'm struggling to make the appropriate tokens for clj-kondo to understand. (more in thread)#2021-11-1117:55otfrommy hook looks like this:
(ns hooks.export-symbols
  (:require [clj-kondo.hooks-api :as api]))

;; export-symbols takes a name space and then a bunch of funcitons in
;; that namespace to export
(defn export-symbols [{:keys [node]}]
  (let [[es ns & fns] (:children node)]
    (when-not (and es ns (seq fns))
      (throw (ex-info "Missing namespace or functions." {})))
    (into []
          (map
           (fn [f]
             (prn "List Node: "
                  (api/list-node
                   (list* (api/token-node 'def)
                          f
                          (concat ns "/" f))))))
          fns)
    {:node
     (into []
           (map
            (fn [f]
              (api/list-node
               (list* (api/token-node 'def)
                      f
                      (concat ns "/" f)))))
           fns)}))
#2021-11-1117:56otfromthe code I'm checking looks like this:
(ns tech.v3.datatype.foo
  (:require [tech.v3.datatype.datetime.base :as datetime-base]
            [tech.v3.datatype.export-symbols :refer [export-symbols]]))

(export-symbols tech.v3.datatype.datetime.base
                system-zone-id)
#2021-11-1117:56borkdudeI'll be back after dinner#2021-11-1117:57otfromthe macro-expand is doing this:
(do
  (require 'tech.v3.datatype.datetime.base)
  (let*
    [varval__5802__auto__
     (requiring-resolve
       (symbol "tech.v3.datatype.datetime.base" "system-zone-id"))
     var-meta__5803__auto__
     (meta varval__5802__auto__)]
    (if varval__5802__auto__
      nil
      (do
        (throw
          (ex-info
            (format
              "Failed to find symbol '%s' in namespace '%s'"
              "system-zone-id"
              "tech.v3.datatype.datetime.base")
            {:symbol 'system-zone-id,
             :src-ns 'tech.v3.datatype.datetime.base}))))
    (if (:macro var-meta__5803__auto__)
      (do
        (throw
          (ex-info
            (format
              "Cannot export macros as this breaks aot: %s"
              'system-zone-id)
            {:symbol 'system-zone-id}))))
    (def system-zone-id (deref varval__5802__auto__))
    (alter-meta!
      #'system-zone-id
      merge
      (select-keys
        var-meta__5803__auto__
        [:file :line :column :doc :column :tag :arglists]))))
#2021-11-1117:58borkdude@U0525KG62 you can try the :macroexpand hook as well, then you can re-use parts of the original macro#2021-11-1117:58otfromwhich is basically expanding
(export-symbols tech.v3.datatype.datetime.base
                system-zone-id)
to
(def system-zone-id tech.v3.datatype.datetime.base/system-zone-id)
#2021-11-1117:58borkdudesee the hooks.md docs, search for :macroexpand. I'll be back in an hour#2021-11-1117:58otfromthx. I'll have a look again#2021-11-1118:00otfrom:macroexpand looks good. I was hoping I'd be able to get something that pointed at the right lines in the source file#2021-11-1118:04otfromright, :macroexpand seems to "just work" ™️#2021-11-1118:05otfromI've got a config.edn with the following:
{:hooks {:macroexpand {tech.v3.datatype.export-symbols/export-symbols
                       hooks.export-symbols/export-symbols}}}
#2021-11-1118:06otfromand I just copy-pasta'd the export-symbols macro from tech.v3.datatype.export-symbols and things are good now#2021-11-1118:10otfromIIUC, putting this config in the .clj-kondo of the project where the macro is defined will mean that it works for all projects that use that macro (so I only need to define it once)#2021-11-1118:17otfromPR here: https://github.com/cnuernber/dtype-next/pull/45#2021-11-1118:56borkdude@U0525KG62 I'm back#2021-11-1118:56borkdude> IIUC, putting this config in the .clj-kondo of the project where the macro is defined will mean that it works for all projects that use that macro#2021-11-1118:57borkdudeNope this isn't true. It works only for the current project. If you want to share it with other projects, put it in clj-kondo.exports#2021-11-1118:57otfromah. Thx!#2021-11-1118:57borkdudeSame documentation page, but a little bit towards the bottom#2021-11-1118:57otfromme goes to look at clj-kondo.exports#2021-11-1118:58borkdudeThe recommendation is to put it in resources/clj-kondo.exports/cnuernber/dtype-next/config.edn#2021-11-1118:58otfromI'm guessing read this: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2021-11-1118:59borkdudeand also namespace the hooks code:
resources/clj-kondo.exports/cnuernber/dtype-next/tech/v3/datatype/export_symbols.clj
#2021-11-1118:59borkdudeand then configure accordingly#2021-11-1119:00borkdudeindeed#2021-11-1119:01otfromdoes this mean that clojure-lsp will automagically work as well?#2021-11-1119:01borkdudealmost automagically. after linting dependencies, there will be a .clj-kondo/cnuerber/dtype-next directory with your exported code/config#2021-11-1119:02borkdudeand you have to add this as :config-paths ["cnuerber/dtype-next"] in your config.edn#2021-11-1119:02borkdudethe reason it's not automatically added is to prevent opting into config that you don't want or contains invalid code#2021-11-1119:03otfromis that in the ~/.clj-kondo/config.edn or for the project?#2021-11-1119:03borkdudeproject#2021-11-1119:04borkdudebut you can add this to your home dir as well. but projects have specific versions of deps and configuration can change over versions#2021-11-1119:05borkdudeif you want to add it to your home dir you should do it manually#2021-11-1119:05borkdudeYou can see a list of other library exported config here: https://github.com/clj-kondo/clj-kondo/issues/1383#2021-11-1119:06borkdudeI was considering doing a workshop on clj-kondo hooks at re:clojure but I'm a bit late to the party I think#2021-11-1119:06otfromwould be good as a london-clojurians talk regardless of when 😄#2021-11-1119:06otfrom(still organising after all these years)#2021-11-1119:19otfromthx for the help @borkdude and for :expandmacro#2021-11-1119:22borkdudeMy pleasure. Are you going to do a follow up PR with exports?#2021-11-1122:27otfromI am, but I ran out of brain and time tonight. I'll read up tomorrow and over the weekend and and do a write up so people in scicloj can use it.#2021-11-1122:29borkdudeok, let me know if you're stuck :-)#2021-11-1122:30otfromthx. Will do. I'd still like to find a better way to do the actual linting than the :expandmacro. It looks like I need to understand a lot more about clj-rewrite works though as it seems like that's the data structure I need to make.#2021-11-1122:30otfrombut I'm going to go with what I have for now as that makes things better now.#2021-11-1122:31otfromI don't want the perfect to be the enemy of the good. 🙂#2021-11-1122:40borkdudeyou mean, emit warnings? you can do this using :macroexpand too#2021-11-1217:02mynomotoCan clj-kondo warn on spec redefinitions?#2021-11-1220:25borkdudeWithin the same file you mean?#2021-11-1220:29mynomotoI mean everywhere but would gladly use on the same file too 😉#2021-11-1220:30borkdudeHow would clj-kondo know which spec overwrites which other one?#2021-11-1220:31borkdudeI think you could already use the clj-kondo analysis for this if you want to script this yourself btw#2021-11-1220:35mynomotoIt could be a warning of multiple definitions, no needed to tell which one is overwriting the other.#2021-11-1220:35borkdudeTrue. Are you using clojure-lsp?#2021-11-1220:37borkdudeclojure-lsp already provides navigation to specs using keywords (using the same analysis). perhaps it would be a small extra step for it.#2021-11-1220:38mynomotoIt navigates to one of the multiple definitions ATM.#2021-11-1220:38borkdudeyes. but because it already keeps track of these definitions, it can catch duplicates fairly easily and perhaps warn: this spec is also defined in another file#2021-11-1220:38borkdudecc @UKFSJSM38#2021-11-1220:45ericdalloyes, I think it could work, maybe a custom lint?#2021-11-1220:46borkdudeyes#2021-11-1222:26ericdallo@U05094X3J feel free to create a issue about clojure-lsp warn about duplicate definitions, sane examples would help a lot#2021-11-1423:00Joshua SuskaloHow do I prevent kondo from outputting warnings for referred but unused vars when I do use those vars, but they've got hooks that don't emit those symbols?#2021-11-1423:01Joshua Suskalowell, in this case, it's not a hook, it's :lint-as#2021-11-1423:01Joshua Suskalo
$ clj-kondo --version
clj-kondo v2021.10.19
#2021-11-1423:17Joshua Suskaloah, it seems to only happen when there's an error in a hook#2021-11-1710:30Adam HelinsIs there any way for passing something from the CLI to hooks? Since System/getProperty is not supported by SCI#2021-11-1710:31borkdudeCurrently not. Can you describe your use case?#2021-11-1710:33Adam HelinsNot strictly necessary but it would make my hook more accurate. Essentially, there is a macro selecting code based on a property, akin to the reader conditionals if you will. It would be nice being able to indicate the hook which code should be selected and processed, discarding the rest.#2021-11-1710:35borkdudebut isn't the property depending on the runtime, which is not available in general in static analysis?#2021-11-1710:39Adam HelinsYes, so analysis should be run twice in this case (2 possibilities for selecting code), but it would be best maintaining one config#2021-11-1711:35juhoteperiHey, can I access the var meta in custom hook for defn? Like (defn ^Return foobar [] ...). Taking the fn name node and looking at meta only returns the position info, not :tag.#2021-11-1711:36juhoteperiHa, found it. This is in the node :meta.#2021-11-1711:36juhoteperiHa, found it. This is in the node :meta.#2021-11-1914:24borkdude#2021-11-1920:42borkdudeI'm considering to automatically opt in to configs that are found in:
.clj-kondo/<org>/</lib>/config.edn
From a usability standpoint this would be much better. But there might be some dangers to this. E.g. a library could accidentally export a config which will make clj-kondo crash or get stuck in a loop while expanding a macro or so. Any thoughts?
#2021-12-0420:23dominicmI would love this, is there an issue I can upvote?#2021-12-0420:23borkdude@U09LZR36F I don't think there is one yet. I'll create one now.#2021-12-0420:24dominicmFwiw, my opinion on the security of this is that you're already loading my code I can be as malicious as I want 🙂#2021-12-0420:24dominicmI could modify your .clj-kondo file and add the infinite loop#2021-12-0420:25borkdudefrom which code?#2021-12-0420:26borkdudeissue: https://github.com/clj-kondo/clj-kondo/issues/1483#2021-12-0420:26dominicmIf you've got my library on your cp, you're likely doing a require on it anyway.#2021-12-0420:27borkdudeclj-kondo only executes hook code#2021-12-0420:27borkdudeand hook code doesn't have access to the file system#2021-12-0420:27borkdudeuntil now hook code was always opt-in#2021-12-0420:27borkdudebut 1483 might automate that a bit#2021-11-1920:43borkdudePerhaps this should be an option: :auto-include-configs true which can be set to false in case of difficulties?#2021-11-1920:49lreadYeah, that seems good to me. So the only way exports get imported is if --copy-configs and --dependencies option are specified. So it seems like a deliberate action in itself. Then again, I think clojure-lsp calls with these options so maybe not so obvious in this case.#2021-11-1920:50borkdudeWe might also deprecate --copy-configs and do this automatically now#2021-11-1920:50lreadRight… yeah.#2021-11-1920:50borkdudeSince lsp already does this all the time, there are lots of users that have already opted in without knowing#2021-11-1920:51lreadYeah, so long as there is a way to opt out, auto-opt-in seems like a usability plus.#2021-11-1920:53borkdudeJust wrote a (clj-kondo) macro for my (clojure) macro: https://github.com/babashka/sci/blob/master/resources/clj-kondo.exports/babashka/sci/sci/core.clj#L3#2021-11-1920:54lreadPotemkin-import-vars-like-ish?#2021-11-1920:55borkdude-ish yeah, you write (sci/copy-ns <ns-sym> <sci-object> <opts>) but since it's a macro you don't quote <ns-sym> and <opts>#2021-11-1920:55borkdudeand you would get red squirlies for those in some cases#2021-11-1920:55borkdudethis is for copying an entire Clojure ns to the SCI context#2021-11-1920:56borkdudewhich in some cases even works for macros in CLJS#2021-11-1920:56lreadThat’ll be handy!#2021-11-1920:57borkdudelet's discuss in #sci for follow up on the specifics if you want to know more#2021-11-1920:58lreadI suppose with auto-opt-in for imported configs… the only risk of a support headache would be an errant hook. But I suppose you could blacklist a bad hook if it comes to that. Which it probably won’t.#2021-11-1920:58borkdudeyeah....#2021-11-1921:02lreadAnother option would be to emit clj-kondo warnings for hooks that are present but not activated.#2021-11-1921:02lreadIf you want to be more cautious.#2021-11-1921:02borkdudeI'm thinking about the LSP use case. Do users see those warnings? I usually don't in emacs, unless I go look into some dark corner of some logs#2021-11-1921:05lreadAh, as opposed to squigglies in place? I often show flycheck error list. But there’s a chance I might be odd.#2021-11-1921:05borkdudelsp doesn't work via flycheck#2021-11-1921:06borkdudeclj-kondo could make info warnings on the first line or so: you have this or that config not activated#2021-11-1921:06borkdudebut I'm not sure if that's the way to go#2021-11-1921:06lreadYeah, certainly not as easy for the user.#2021-11-1921:08borkdudemaybe the automatic feature should be opt-in then#2021-11-1921:08borkdudefor a while#2021-11-1921:08borkdudeand after that while, we can re-consider#2021-11-1921:08lreadNot sure why but I do see lsp warnings. I use spacemacs.#2021-11-1921:09borkdudePerhaps @UKFSJSM38 could enlighten us.#2021-11-1921:11lreadHe often does! simple_smile#2021-11-1921:47ericdalloyeah, that looks lsp-mode is working indeed with clojure-lsp#2021-11-1921:49ericdalloactually, lsp-mode use flycheck by default, you can use flymake if you want#2021-11-1921:53ericdallothere is a custom code on lsp-mode that register a lsp-flycheck, all LSP diagnostics use that: ref: https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-diagnostics.el#L36#2021-11-1922:02borkdudeah I see!#2021-11-1922:02borkdudeI'm also using flycheck.. I think#2021-11-1922:02borkdudeat least for clj-kondo#2021-11-1922:03borkdudebut I was thinking about errors here#2021-11-1922:03borkduderuntime errors... lsp logs them to a file but doesn't show them as diagnostics#2021-11-1922:03ericdallowhat kind of runtime errors?#2021-11-1922:04borkdudenull pointer exceptions for example#2021-11-1922:04ericdalloyeah, we only show on log indeed, not sure it makes sense to use diagnostics feature for NPE that could happen anywhere on the code#2021-11-1922:04ericdallofor example a NPE during the process of lsp-lens#2021-11-1922:04borkdudeI'm also not sure#2021-11-1922:05ericdalloUsually, LSP diagnostics are related to user's code, a NPE means a clojure-lsp or third error, user don't care about that, but if something stops working and he wants to understand he should seek the logs I think#2021-11-1922:06ericdalloor at least we catch the excpetion, log and show a pretty message like "Some error ocurred"#2021-11-1922:06ericdallowe already support that custom friendly message, we just show for specific actions#2021-11-1922:07ericdallolike user tries to rename something, and we can't for some reason, we return that message explanining why we couldn't rename#2021-11-1922:08borkdudeclj-kondo does show some errors as lint messages#2021-11-1922:08borkdudelike: parse error such and so#2021-11-1922:08ericdalloyeah, but they are related with a error in user's code right#2021-11-1922:08borkdudetrue.#2021-11-1922:09borkdudeor with the config#2021-11-1922:09ericdalloI got your point, I just think LSP showMessage would be something that should fit better#2021-11-1922:09ericdallohttps://microsoft.github.io/language-server-protocol/specification#window_showMessage#2021-11-1921:46ericdallosorry for the delay: > Since lsp already does this all the time, there are lots of users that have already opted in without knowing Yes, having that enabled by default would be really good for users IMO, the corner case probably could be solved with a option to disable a hook or something like you mentioned > I'm thinking about the LSP use case. Do users see those warnings? I usually don't in emacs, unless I go look into some dark corner of some logs Yeah, they will only see the warnings if they search on the logs, is not something we show activelly for the users.#2021-11-1921:55ericdallo@borkdude at Nubank we created a common lib that has all necessary clj-kondo config-paths and all services use that, with that we avoid the need to add that config for each service, it works really well, so IMHO I'd go with a default true flag which could be opt-out#2021-11-2002:50Noah Bogarti would prefer to have them be automatic#2021-11-2017:04Adam Helins(not (empty? ...))  issues a warning (use `seq` idiom instead) However, when this is the last form in a function for instance, the result is not the same (returning a boolean vs ?seq) I would suggest issuing this warning only when used in a conditional (`if` and friends) 🙂 (edited)#2021-11-2017:06borkdudeor suggest (boolean (seq ...)) ;)#2021-11-2017:06borkdudeI don't know, clj-kondo just reflects what's in the docstring of empty?, empty? doesn't suggest the context of a condition#2021-11-2017:08Adam HelinsYep or just disable that linter since it's not super crucial#2021-11-2017:09borkdudeas you see fit#2021-11-2017:10borkdudeyou can also locally ignore it with #_:clj-kondo/ignore#2021-11-2017:36Adam HelinsAh, is that new? I don't remember reading about that#2021-11-2017:43borkdudeit's been there for a while#2021-11-2017:44borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#v20200909#2021-11-2208:13orestisPerhaps if not a macro, then something that clj-kondo could do (in principle)? https://clojurians.slack.com/archives/C03S1KBA2/p1637568739382000#2021-11-2208:24borkdude@orestis you can make custom macro/function hooks in which you can do this checking yourself#2021-11-2208:24borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-11-2208:25orestishm, would hiccup syntax also work? e.g. the ideal use case is that the callsite is: [text/Text {:variant "Large" :color "Main"} "here is some text"] and I can validate "Large" and "Main" against a static set of values.#2021-11-2208:27borkdudethen you would have to add a hook for text/Text (with the namespace fully qualified)#2021-11-2208:29orestiseven if it's not a function call?#2021-11-2208:30borkdudeoh right#2021-11-2208:30borkdudeno that currently doesn't work#2021-11-2208:31borkdudeyou could consider using https://github.com/borkdude/grasp to search for this pattern, but this is more offline than in your editor#2021-11-2208:33borkdude
(g/vec (g/rsym 'full.ns.text/Text) (s/and map? ...) g/*)
#2021-11-2209:25borkdude@orestis Here is a full example:
user=> (require '[grasp.api :as g])
nil
user=> (def spec (g/vec (g/rsym 'foo.text/Text) (s/and map? #(:variant %))))
#'user/spec
user=>
user=> (g/grasp-string "(require '[foo.text :as text]) [text/Text {:variant \"Foo\"}])" spec)
[[text/Text {:variant "Foo"}]]
user=>
user=> (def results *1)
#'user/results
user=> (map (fn [res] (-> res second :variant)) results)
("Foo")
user=>
#2021-11-2209:31orestisoh that's nice.#2021-11-2210:55Benjaminwhat do I do wrong if update-vals is an unresolved symbol? It's in clojure.core#2021-11-2211:01delaguardoMost likely you are using clojure before 1.11#2021-11-2211:01borkdude@benjamin.schwerdtner It works out of the box with clj-kondo, but if you have a dependency of Clojure older than 1.11 alpha such and so, it's not in there. And if this dependency is used for linting then it overwrites the built-in cache for clojure.#2021-11-2211:02Benjaminso the issue is that the linting version is too old#2021-11-2211:03borkdudeit depends on what you are linting yes#2021-11-2211:05Benjaminmy /usr/bin/clojure is clojure 1.10 so and so. I guess that is the problem? The lint target uses 1.11#2021-11-2211:05borkdudeare you using clojure-lsp? or just vanilla clj-kondo?#2021-11-2211:06Benjaminvanilla#2021-11-2211:07borkdudehave you linted your dependencies and how? which version of clj-kondo are you using?#2021-11-2211:07Benjaminclj-kondo v2021.06.18#2021-11-2211:07borkdudeplease upgrade#2021-11-2211:08Benjaminupgrading to 2021.10.19-1 from the AUR#2021-11-2211:08borkdudethat should fix it#2021-11-2211:08Benjaminyea works#2021-11-2211:53Joshua SuskaloSo this is back on friday, but I also get the lsp errors in my flycheck error list that I get integration for with treemacs-list-errors, and I definitely go through them all, and I definitely get the errors that don't have line numbers that way.#2021-11-2211:59Joshua SuskaloAh, I see that was resolved.#2021-11-2213:40Joshua SuskaloWhat would be a reason I'm getting an unresolved var warning for a #' var form with the fully qualified name of a public var?#2021-11-2213:51borkdudeunresolved var means: could not be found in the analysis of the other namespace#2021-11-2214:00Joshua Suskalohmm. I'll take a look in the ns to see how it's defined#2021-11-2214:03Joshua Suskaloah, they're using a custom def macro.#2021-11-2215:04dharriganFunnily enough, I'm getting this, but it's a bit weird, since I'm seeing, in the same namespace, where it is saying unsolved var (yet the var exists in the other namespace), and just above the undefined vars, are vars it can find, that have the same macro.#2021-11-2215:04Joshua Suskalokondo only reports a single var once per file I believe#2021-11-2215:06borkdudeit does, but it is configurable to show them all at once#2021-11-2215:06dharriganRight, but have a looksee at this:#2021-11-2215:06dharrigan#2021-11-2215:07dharriganthe two hightlighted do exist in the namespace referenced#2021-11-2215:07dharriganand both do follow the same structure at the ones that can be found#2021-11-2215:07dharriganeach of those "public routes" is defined using the same macro#2021-11-2215:07borkdudebut did you visit that file recently? e.g. has clj-kondo linted that one - perhaps it has recent modifications or you checked out a git branch?#2021-11-2215:08dharriganI visit it a lot#2021-11-2215:09dharriganthat's just a snippet. Imagine, if you will, that that list continues on for several more lines. clj-kondo finds most of the public-routes, but raises the same exception for others in the list (that do exist!)#2021-11-2215:10dharriganI count 12 lines it flags that error with#2021-11-2215:10borkdudeas always repro welcome. something that I can run locally.#2021-11-2215:10dharriganYeah. I know. Pity I can't share the code as-is, etc.. etc..#2021-11-2215:10dharrigan🙂#2021-11-2215:12borkdudemaking a minimal repro sometimes isn't that hard. yesterday I cut down a minimal repro from several hundred lines to 5 characters in a minute ;)#2021-11-2215:12borkdudeand this is the only way I can help. I haven't got any other ideas without more info#2021-11-2215:12dharriganI'm trying to do now#2021-11-2215:13dharriganI have a nice template that will generate a project for me, having to try to reproduce there#2021-11-2215:48mynomotoIs there something like grasp that also transforms what it find?#2021-11-2215:49borkdude@mynomoto the idea is that you can find matching results and then transform those results, e.g. using s/conform or whatever you like#2021-11-2215:49borkdudeor do you mean, in the file of the code itself?#2021-11-2215:50mynomotoYeah, in the code itself.#2021-11-2215:50mynomotoLike grep can replace.#2021-11-2215:50borkdudeThere you will need something like grasp + rewrite-clj. Grasp gives you the locations, and rewrite-clj allows you to update clojure code.#2021-11-2215:51borkdudeSee #rewrite-clj#2021-11-2215:51mynomotoYou have a fork that ignores white spaces right?#2021-11-2215:52borkdudeyes, but this fork cannot be used to update code. since it does not have the whitespace#2021-11-2215:53mynomotoHum, interesting. Even if I do not care about the whitespace?#2021-11-2215:54borkdudeif you use rewrite-clj's zippers, you can navigate while it also takes into account whitespace. yes: my fork just ignore the whitespace during reading. if you don't have those tokens, you cannot produce the code reliably anymore. well, I guess you could by just looking at the locations and inserting whitespace, but you won't know if there were tabs or spaces.#2021-11-2215:55borkdudeI did this basically because I wanted to use rewrite-clj only for analysis, not rewriting#2021-11-2215:55borkdudeand I also didn't want to use zippers#2021-11-2215:57lread@mynomoto like borkdude suggests, the rewrite-clj zip API will skip whitespace and comments while navigating but it preserves them.
#2021-11-2215:58borkdude@mynomoto carve is a tool which uses clj-kondo for analysis, gets locations and then uses the original rewrite-clj to update code#2021-11-2215:58borkdudeI think it's good to have separate tools for what you want: finding problem locations in code vs updating code using locations#2021-11-2216:03mynomotoOk, thank you both for the pointers/suggestions!#2021-11-2216:05dharriganWould it be significant that if I run clj-kondo on the command line, for that particular file, it does not report unresolved var, but when editing the file in my editor, that uses clojure-lsp (with clj-kondo under the hood), that the warning is produced?#2021-11-2216:06borkdudeyes, the cache is versioned with the version of clj-kondo, so if clojure-lsp uses a different version, then the used cache won't be the same#2021-11-2216:06borkdudeyou will have to lint your dependencies in the same way that clojure-lsp does it#2021-11-2216:07dharriganI delete both the .clj-kondo directory and the .lsp directory each time#2021-11-2216:07borkdudethat's fine but clojure-lsp will automatically index all your dependencies#2021-11-2216:07borkdudeso the warnings will only appear if you linted certain namespaces#2021-11-2216:08borkdudebecause then clj-kondo thinks it knows all the vars in those namespaces#2021-11-2216:08borkdudeand then warns about those that it thinks are not in them#2021-11-2216:08dharriganRight, if I get clj-kondo to lint the entire source directory, the warning is displayed.#2021-11-2216:08dharriganso, at least that is something to rule out.#2021-11-2216:11ericdalloyeah, the unresolved-var linter from kondo is one of the linters that relies on the cache, since it need to know the namespaces available + their var-definitions#2021-11-2216:12ericdalloyou can repro manually with kondo if you lint with the same version clojure-lsp as well#2021-11-2216:12ericdallowould you mind me ask why you want to run kondo manually for your case?#2021-11-2216:13dharriganI was simply trying to determine by a process of elimination what is causing the warning to be displayed#2021-11-2216:13dharriganso I wanted to try clj-kondo "raw" just to see if it produced the same result.#2021-11-2216:14ericdallogot it#2021-11-2216:14ericdalloin the past we had false-positives with this linter, but AFAIK we fixed them#2021-11-2216:15dharriganyeah, in this case I still don't know why I'm getting this oddness.#2021-11-2216:15dharriganI'm unable to reproduce atm in my test project#2021-11-2217:03dharriganYeeeah!#2021-11-2217:03dharriganI can reproduce it!#2021-11-2216:24dharrigan@borkdude did you say that it's possible for clj-kondo to show all unresolved vars, not just the first one?#2021-11-2216:24dharrigan where is that configured?#2021-11-2216:37dharriganAh, I see :report-duplicates#2021-11-2217:22dharrigan@borkdude I can reproduce it. I'm going to raise an issue for you to have a look when you have time 🙂 I also have a project you can use.#2021-11-2217:23borkdudeAwesome!#2021-11-2219:31dharrigan#2021-11-2219:35borkdudethanks, I'll take a look soon#2021-11-2219:46dharriganYou're most welcome. Let me know if I can be of further assistance.#2021-11-2219:46dharrigan.#2021-11-2219:50borkdudeI think a better solution would be if compojure.sweet.api had some proper clj-kondo hook expansions, but I'm not sure how much this is used anymore, it has becomes a little bit of a legacy compared to reitit right?#2021-11-2220:31dharriganYes, reitit has superceeded it#2021-11-2217:24dharrigan🙂#2021-11-2220:00seancorfieldWhat's the recommended approach for projects that get clj-kondo configs exported into them from dependencies? Check that into version control or not?#2021-11-2220:00seancorfield
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	../.clj-kondo/com.github.seancorfield/next.jdbc/
#2021-11-2220:01seancorfield(because the latest version of next.jdbc exports its hooks etc)#2021-11-2220:03borkdude@seancorfield yes, just check it into source control. so anyone who check outs your project has the same linting, and also CI has the same linting.#2021-11-2220:07borkdudeyou also have to add this to .clj-kondo/config.edn :config-paths ["com.github.seancorfield/next.jdbc"] I'm considering doing this automatically (implicitly) but I'm not yet sure if this is a good idea or what could go wrong#2021-11-2220:09borkdudethe danger would be: malfunctioning configs or never-ending loops in hooks for example#2021-11-2220:13borkdudeWe could have a file to which we append automatically when importing/copying configs .clj-kondo/config-paths.edn (wrapped implicitly in a map):
"com.github.seancorfield/next.jdbc" true
".../..." false
and when there is already an entry (e.g. with false ) then we do not override that. thinking-face
#2021-11-2220:20seancorfieldHmm, glad I asked. I didn't realize I needed to manually update config when something got exported into my project.#2021-11-2220:20borkdudeyes, the reason is that I think people should be able to opt in or opt out of these configs#2021-11-2220:23borkdudewe could also just have a .config_ignore file which contains paths not to ever import.#2021-11-2220:24borkdudeor just part of config.edn :config-ignore-paths [".."]#2021-11-2221:30Mateusz MazurczakHi, I wrote my own hook is it enough to just run clj-kondo --lint "src" after updating config.edn or am I missing something? Because it seems like it doesn't include my newest changes#2021-11-2221:33Mateusz Mazurczakconfig.edn
{:linters {:translate/unwrapped {:level :error}}
 :hooks {:analyze-call {foo/unwrapped hooks.unwrapped/register-unwrapped}}}
and the hook:
(ns hooks.unwrapped
    (:require [clj-kondo.hooks-api :as api]))

(defn register-unwrapped [{:keys [:node]}]
    (let [test (println "HELLO")]
          (api/reg-finding!
            {:message "HELLO WORLD"
             :type :translate/unwrapped
             :row (:row (meta node))
             :col (:col (meta node))})
      ))
#2021-11-2221:48borkdude@U0281QDFE1X in which directory did you put the hook code?#2021-11-2221:48borkdudeand what is the file called?#2021-11-2221:52Mateusz Mazurczak@borkdude .clj-kondo/hooks/unwrapped.clj#2021-11-2221:52Mateusz Mazurczakit's the hook file path from the root of the project#2021-11-2221:53borkdudethat looks good#2021-11-2221:54borkdudeand you don't see anything when you lint
(require '[foo.bar :as foo])
(foo/unwrapped 1 2 3)
?
#2021-11-2221:54Mateusz MazurczakSo I run clj-kondo --lint "src" and I get old warnings, but no errors, also no println#2021-11-2221:55Mateusz MazurczakIt seems that clj-kondo works, but it does not run the hook. As there should be errors from this hook#2021-11-2221:56borkdudeyes, with "see" I meant see the output from println#2021-11-2221:56borkdudecan you give an example including the require/ns form of what you are linting?#2021-11-2222:01Mateusz MazurczakHmm what do you mean by > and you don't see anything when you lint > (require '[foo.bar :as foo]) > (foo/unwrapped 1 2 3) ohh so this hook is not run automatically through every namespace?#2021-11-2222:03borkdudecan you give me an example?#2021-11-2222:03borkdudeso I can see what you are doing#2021-11-2222:03borkdudeyou need to use the fully qualified namespace in the config#2021-11-2222:03borkdudenot an alias#2021-11-2222:03borkdudethis is why I want to check in your example#2021-11-2222:05Mateusz MazurczakI think I've misunderstood how hooks work. I was expecting it to run this hook through all functions in "src" directory and if the hook function gets to the (reg-finding! ...) it reports error#2021-11-2222:06borkdude:analyze-call {foo.bar/baz ....} is executed for functions like this:
(require '[foo.bar :as fbar])
(fbaz/baz 1 2 3) ;; <-- the hook sees this node
#2021-11-2222:10borkdudewhat would be your use case for running a hook on all function calls?#2021-11-2222:13Mateusz MazurczakNow I understand how hook works. Thanks! I want to add a lint rule, for checking reagent dom tree. There is a bug that if there is text that is not wrapped in :span tag, google translate add tags to it and react throws error that it cannot remove the child. So I wanted to check every function if there is for example "[:div "Hello"] and throw message that this "Hello" needs to be wrapped in [:span]#2021-11-2222:16borkdudeMakes sense. Currently hooks don't really provide access to this. Perhaps you can use something like https://github.com/borkdude/grasp. I gave an example of that here: https://clojurians.slack.com/archives/CHY97NXE2/p1637573107258800#2021-11-2222:17borkdudeThis allows you to basically "grep" Clojure code using clojure.specs#2021-11-2222:18borkdudeSo this spec would be something like:
(g/vec #{:div} string? g/*)
#2021-11-2222:19Mateusz MazurczakThanks! But with hook, couldn't I just hook to every "defn" function call to see if there is div?#2021-11-2222:20borkdudeyes, I guess you could#2021-11-2222:20borkdudefull grasp example:
user=> (require '[grasp.api :as g])
nil
user=> (def results (g/grasp-string "(defn foo [] [:div \"Hello\"])" (g/vec #{:div} string? g/*)))
#'user/results
user=> results
[[:div "Hello"]]
user=> (map meta results)
({:line 1, :column 14})
#2021-11-2318:15chrisnI would like to add clj-kondo support to dtype-next. Is the method used in https://github.com/clj-python/libpython-clj/pull/135/files the best way to add it the the dtype-next jar and thus enabling support for many downstream projects?#2021-11-2318:30borkdude@chris441 yes. additionally you can add your own exported config to your own .clj-kondo/config.edn using :config-paths ["../resources/clj-kondo.exports/org/lib"]#2021-11-2318:31borkdudeand additionally there is now also a :macroexpand hook which allows you to write a macro in the same fashion as clojure - this is easier than writing a hook but gives less precise locations of errors#2021-11-2318:31borkdudeThat info is available on this page: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-11-2318:57chrisnWhat I would like most is for tablecloth, http://metamorph.ml, http://tech.ml.dataset, etc. to all get automatic support for clj-kondo. I am specifically trying to avoid a pathway that is user-specific but instead update just the dtype-next jar and have the downstream systems work automatically. The end hope is to get auto-complete working for those systems in clojure-lsp and thus transitively in Calva.#2021-11-2320:35ericdallo@chris441 I already did some of those configs on upstreams project so I can help you if you want#2021-11-2320:35ericdalloIMO providing the hook on the upstream package is the best way to make downstream just work with minimal config#2021-11-2402:29chrisnThat is great to know - I appreciate the offer and I will be taking you up on that :-)#2021-11-2402:30ericdallo:) Some libs I added clj-kondo hooks and custom config that worked for downstreams: https://github.com/nubank/state-flow/blob/master/resources/clj-kondo.exports/nubank/state-flow/config.edn https://github.com/marick/Midje/tree/master/test-resources/clj-kondo.exports/marick/midje#2021-11-2319:14danielcomptonIs there a way for clj-kondo to lint for incorrect kwargs usage? ClojureScript used to be more lenient in what it accepted but now matches Clojure https://clojurians.slack.com/archives/C07UQ678E/p1637632148130100#2021-11-2320:48borkdude@danielcompton See my reaction over there.#2021-11-2322:39seancorfield@borkdude Is anything needed to get clj-kondo to recognize the new core functions in Clojure 1.11 Alpha 3? Is it just a matter of deleting the caches and having LSP/clj-kondo regenerate them?#2021-11-2322:40borkdudeif you're lucky, yes#2021-11-2322:40seancorfieldThanks. Will try that and let you know 🙂#2021-11-2322:49borkdude@seancorfield Actually I think just changing your deps.edn and restarting your editor should trigger lsp to rescan the deps. But @ericdallo can probably verify this.#2021-11-2322:49seancorfieldIt did not.#2021-11-2322:50seancorfieldWell, it did rebuild the .caches etc, but clj-kondo still thinks random-uuid is unknown.#2021-11-2322:51borkdudehmm, is there another clojure version on your classpath that overrides it?#2021-11-2322:51seancorfieldNot as far as I know.#2021-11-2322:51borkdudeI'll try it#2021-11-2322:53seancorfieldI checked the classpath that LSP uses:
/Users/sean/.m2/repository/org/clojure/clojure/1.11.0-alpha3/clojure-1.11.0-alpha3.jar
is the only Clojure on it.
#2021-11-2322:54seancorfieldLSP config:
{:project-specs [{:project-path "clojure/deps.edn"
                  :classpath-cmd ["./.lsp/classpath.sh"]}]}
and that script is
#!/bin/sh
cd clojure && clojure -Spath -M:build:dev:everything:runner:test
#2021-11-2322:55borkdudeWhen I lint clojure 1.11.0-alpha3 myself and use vanilla clj-kondo without LSP it works.#2021-11-2322:56borkdudeWhat does clojure -Spath -M:build:dev:everything:runner:test return?#2021-11-2322:56borkdudeOnly clojure 11?#2021-11-2322:57borkdude@ericdallo Does LSP skip linting clojure itself?#2021-11-2323:00borkdude@seancorfield can you try ls -la .clj-kondo/.cache/2021.10.20-SNAPSHOT/clj/clojure.core.transit.json in your project? This should contain the cached analysis of clojure.core. The clj-kondo version might differ.#2021-11-2323:00borkdudeIf that transit file is not there, then clojure.core wasn't analyzed#2021-11-2323:00seancorfield-rw-r--r-- 1 sean admin 74976 Nov 23 14:42 .clj-kondo/.cache/2021.10.20-SNAPSHOT/clj/clojure.core.transit.json#2021-11-2323:01seancorfield(at the top of the project, but the .clj-kondo in the clojure folder of the project does not have it.#2021-11-2323:01seancorfield(this was my weird issue with having two .clj-kondo folders in the project)#2021-11-2323:02seancorfieldI could make ./clojure/.clj-kondo a symlink up to ./.clj-kondo#2021-11-2323:02borkdudethen it seems lsp picks the wrong root#2021-11-2323:02borkdudewell no#2021-11-2323:02borkdudelsp looks from the working directory upwards, not downwards#2021-11-2323:02seancorfieldLSP has the correct root. But clj-kondo seems to run against the directory the REPL is starting against.#2021-11-2323:03borkdudehow are you opening this project in vscode?#2021-11-2323:03seancorfieldIt's a workspace with two folders wsmain and worldsingles. The Clojure code is in wsmain/clojure.#2021-11-2323:04borkdudeI think you should open the clojure directory in vscode, Calva is quite sensitive to what directory you open#2021-11-2323:04seancorfieldNo, wsmain is the project folder. That's where git is rooted.#2021-11-2323:05borkdudethen why does your bash script cd into another directory?#2021-11-2323:05seancorfieldBecause that's where deps.edn is.#2021-11-2323:05borkdudeyes. so your working directory is wsmain, but your actual clojure project is in wsmain/clojure. you should open wsmain/clojure in vscode I think, to set the correct working directory#2021-11-2323:05seancorfieldThe repo has build, clojure, documentation etc.#2021-11-2323:06seancorfieldNo. wsmain is the folder I need to have open in VS Code. Otherwise it screws up git behavior.#2021-11-2323:06seancorfieldI'll just use a symlink for .clj-kondo. I think that solves it.#2021-11-2323:06borkdudethis seems to be a downstream issue. clj-kondo behaves similar in emacs like you want it. but vscode / calva /lsp does not agree with this. :)#2021-11-2323:08borkdudeyou can also try the standalone clj-kondo plugin for vscode which works similar to the one in emacs I think#2021-11-2323:08borkdudeand then disable lsp diagnostics#2021-11-2323:08borkdudebut it doesn't automatically lint deps. you should do that from the command line with the same version#2021-11-2323:10borkdudeperhaps this can be fixed with calva/lsp. what clj-kondo does by default is, it tries to resolve the config directory from the file you're editing. but lsp is passing the config dir explicitly which overrides this and if it picks the wrong one then it doesn't work as you expect.#2021-11-2323:16seancorfieldUsing a symlink "fixes" the problem. I can live with that.#2021-11-2323:18borkdudecool#2021-11-2323:33ericdalloI didn't understand exactly what clojure-lsp is doing wrong, LMK if need help debugging that#2021-11-2323:42seancorfieldI'll try to explain: my repo root is wsmain LSP creates .lsp there (as expected for Calva usage). My REPL is started in wsmain/clojure. The classpath script for LSP cd's into clojure to run clojure -Spath ... because that's where deps.edn is.#2021-11-2323:42seancorfieldHowever, I end up with TWO .clj-kondo folders. One in wsmain and one in wsmain/clojure.#2021-11-2323:43seancorfieldBoth of them get the exported configs from dependencies. Both of them get a .cache folder -- but the contents seem to be different.#2021-11-2323:43seancorfieldI don't know why the clojure/.clj-kondo folder is created.#2021-11-2323:44seancorfieldI thought the setup with Calva was such that it only ran clj-kondo via LSP and so I expected that wsmain/.clj-kondo would be the only folder created.#2021-11-2323:44ericdalloI'd suggest not having your root not on the same folder of your deps.edn but I think you have your reasons, you probably need to setup more than just project-specs if you are doing that#2021-11-2323:45ericdallolike :source-paths#2021-11-2323:45ericdalloanyway, it doesn't make sense create a clojure/.clj-kondo indeed since clojure-lsp creates that from the passed project-root-uri that calvas sends on the initialize request#2021-11-2323:46seancorfieldNot sure what :source-paths you are referring to?#2021-11-2323:46seancorfield.lsp/config.edn is
{:project-specs [{:project-path "clojure/deps.edn"
                  :classpath-cmd ["./.lsp/classpath.sh"]}]}
#2021-11-2323:46ericdallohttps://clojure-lsp.io/settings/#source-paths-discovery#2021-11-2323:47ericdallosince the source-paths discovery will not work because there is no deps.edn on the project-root, you should specify manually it with the :source-paths lsp settings#2021-11-2323:47seancorfieldThis is a monorepo with dozens and dozens of subprojects that are :local/root deps.#2021-11-2323:47seancorfieldThe classpath will contain all those directories tho'#2021-11-2323:48ericdalloyeah, the classpath thing should work, but other clojure-lsp features like rename namespaces and some others that rely on correctly configured source-paths won't#2021-11-2323:48seancorfieldI don't care about refactorings.#2021-11-2323:49seancorfieldOnly linting.#2021-11-2323:49ericdalloalright, so it should work, not sure why is creating the clojure/.clj-kondo dir, are you sure there are no extra plugins anything?#2021-11-2323:50ericdalloThis is clojure-lsp code that creates the kondo dir, it only checks the project-root-uri sent by the client (calva): https://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/crawler.clj#L176-L185#2021-11-2323:52seancorfieldJust Calva and Clover and I'm pretty sure the latter doesn't do anything with clj-kondo?#2021-11-2323:52ericdalloyeah I think so#2021-11-2323:53ericdallowell, clojure-lsp logs when it's creating the kondo dir, maybe you can search there#2021-11-2323:54ericdallosearch for "creating for necessary clj-kondo analysis..."#2021-11-2323:54ericdalloI think there is a calva command to get clojure-lsp logs#2021-11-2323:54ericdalloCalva Diagnostics: Open Clojure-lsp Log File#2021-11-2323:56seancorfieldLooks like I'd need to do a clean restart without those folders to see what it is doing? That's going to be too disruptive right now but I'll try to set aside some time for that tomorrow.#2021-11-2323:56ericdalloyes#2021-11-2406:37pezNot sure I follow fully, but I'll try to see what Calva gives to clojure-lsp in this scenario. #2021-11-2408:12pezI can’t see that Calva configures any project root for clojure-lsp. Should we?#2021-11-2408:24borkdude@U0ETXRFEW It has to do with the concept of workspace / working directory. I think Calva and LSP have just one concept of what the project root is.#2021-11-2408:24borkdudeSo if you work inside a sub-directory in your workspace the project root is still the root directory.#2021-11-2408:31pezCalva has a concept of project root that is used for various things. This is currently determined from the current file and then upwards looking for a project file. I have on my todo to revisit this to better support monorepos, polylith, etc. I don’t see that we send this info to clojure-lsp, though. And from what I take from this thread, it would risk mess things up if we did? Maybe VS Code is giving clojure-lsp some project root automagically…#2021-11-2408:32borkdudeok, then we should ask @ericdallo.#2021-11-2408:34borkdudeThis is how the clj-kondo LSP plugin does it: for every file that you edit, regardless of what is your working directory, it looks up from the path of that file for the config directory, https://github.com/clj-kondo/clj-kondo.lsp/blob/b1097c318c0d51b3c7e45192005c0f7d8765cd68/server/src/clj_kondo/lsp_server/impl/server.clj#L130#2021-11-2408:34borkdudeThis approach should work for Sean's situation#2021-11-2412:43ericdalloThe project-root-uri is a mandatory string that clients should send, if calva is not sending manually then vscode is, probably it uses the current folder root opened or something. It's possible to get that in LSP logs like I mentioned above#2021-11-2412:49borkdude@ericdallo the clj-kondo.lsp plugin doesn't care about it though. it just uses the file path to scan upwards for a config#2021-11-2412:50borkdudeEDIT: I meant clj-kondo.lsp, not clojure.lsp.#2021-11-2412:52pezI think it makes sense that clojure-lsp does what clj-kondo.lsp does for this. Calva should probably share what it thinks is the project root anyway, but it seems to be a bit unrelated?#2021-11-2412:52pezCC: @U9A1RLFNV#2021-11-2412:53ericdalloWe could improve that on clojure-lsp I think, but that would work for single file edits only, not full project lint on startup as we pass project sources to kondo#2021-11-2412:54ericdalloBut it'd solve most issues I think#2021-11-2412:54ericdalloActually, this is the first one I see#2021-11-2412:54borkdudeI wonder what the reason is that Sean doesn't just open the sub-project directory. He mentioned issues with git that way#2021-11-2412:56ericdalloyeah, I agree clojure-lsp could have better mono-repo support, I improved that for polylith and other mono-repos, but threre are lot of cases#2021-11-2412:58pezI know that feeling!#2021-11-2423:16bringeJust FYI, you can see what root path is being sent from VS Code / Calva in the Clojure Language Client output channel, if the setting clojure.trace.server is set to verbose . The info is in the initialization message.#2021-11-2519:22seancorfield#2021-11-2519:22seancorfieldThat's what showed up with verbose tracing and a fresh setup (no .clj-kondo folder)#2021-11-2519:24borkdudefor context: your .clj-kondo folder is in wsmain/clojure/.clj-kondo, correct?#2021-11-2519:24seancorfieldNo, it's in wsmain/.clj-kondo#2021-11-2519:24seancorfieldI've removed the wsmain/clojure/.clj-kondo folder.#2021-11-2519:24seancorfieldLSP creates it in the root of the tree.#2021-11-2519:25borkdudeok#2021-11-2519:26seancorfieldI'll keep an eye out for wsmain/clojure/.clj-kondo appearing -- that was what broke things before, but as long as that doesn't get created I think this setup will work just fine.#2021-11-2519:27borkdudeLSP might create it if you open VSCode at wsmain/clojure#2021-11-2519:28borkdudenot sure though.#2021-11-2519:32seancorfieldWill report back if I see that reappear. For a while, it was randomly reappearing, while I was using VS Code, but I don't know what triggered it.#2021-11-2414:48Noah Bogartdoes clj-kondo respect type hints for non-primitives when linting function calls?#2021-11-2414:49Noah Bogart
(defn ^DBObject find-one
  "Returns a single DBObject from this collection matching the query."
  ([^DB db ^String coll ^Map ref]
     (.findOne (.getCollection db (name coll))
               (to-db-object ref))))
coll here is type hinted as a String which doesn’t change anything about how the function actually works (due to the name call), but if I write (mg/find-one db :example {}), I get an error about find-one requiring a string
#2021-11-2414:50borkdudeif you hint it as a string, clj-kondo will think you will have to pass a string or nil there.#2021-11-2414:50Noah Bogartany way I can disable this?#2021-11-2414:51borkdudewhy would you add a type hint that doesn't do anything?#2021-11-2414:51Noah Bogarti didn’t write the library, so I don’t know lol#2021-11-2414:52borkdudeyou're trying to solve lint warnings in libraries?#2021-11-2414:52borkdudeoh I get it, you're calling the function and then get the lint warning#2021-11-2414:54borkdudeyou can override this with {:linters`{:type-mismatch {:namespaces {library {function {:arities {3 {:args [:any :any :any]}}}}}}}}`#2021-11-2414:55Noah Bogartcool, thank you.#2021-11-2414:55borkdudethe exact format is here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/types.md#2021-11-2415:00hugodIn a hook, what’s the best way of adding clj-kondo suppression of certain lints (on the re-written code)? The re-written code defines some things that may not be used.#2021-11-2415:01borkdudeemit code that uses the things#2021-11-2415:02borkdudejust a vector with the things for example#2021-11-2415:03hugodof course, that works - thanks#2021-11-2415:56chrisnFor clj-kondo integration with emacs, there are three possibilities - flycheck-clj-kondo, anakondo, and flymake-kondor. IS there are clear recommendation from the community as to which one is preferred?#2021-11-2415:59DerekIf you already use flycheck, flycheck-clj-kondo#2021-11-2416:00borkdude@chris441 I'm using and maintaining flycheck-clj-kondo myself. But I'm also using clojure-lsp. If I wasn't maintaining clj-kondo myself, I might not be using flycheck-clj-kondo since clojure-lsp already packages clj-kondo.#2021-11-2416:00borkdudeBut as I'm always on the latest master, I'm using flycheck-clj-kondo separately from clojure-lsp.#2021-11-2416:00Derekflymake is built in to emacs, so some people prefer that. especially if they’re using eglot#2021-11-2416:25ericdallo@chris441 check https://clojure-lsp.io/features/, clojure-lsp uses kondo under the hood#2021-11-2417:00chrisnRight, so reading into those answers a bit perhaps using lsp-mode for emacs is also a recommended pathway. Especially since the point of this work is to enable a smoothr \flo#2021-11-2417:00chrisnsorry, baby typing#2021-11-2417:00chrisnflow for calva users and tmd.#2021-11-2417:01chrisnThen, is there a different setup you use if you are going to be configuring kondo hooks and such? Like I guess just running kondo from the command line?#2021-11-2417:02borkdude@chris441 with clojure-lsp there is no need to run clj-kondo from the command line#2021-11-2417:03chrisnIncluding when debugging config macro definitions?#2021-11-2417:03borkdudefor debugging, I would use the command line and println#2021-11-2417:03borkdudebut for seeing feedback in the editor from your hooks using clojure-lsp should be enough#2021-11-2417:06chrisn@dpassen1 - I currently intermittently use flycheck-joker. But I want to integrate correct clj-kondo hooks into our stack which is kind of extensive so switching that portion of my system is the just not a big deal work-wise as compared to the actual work of going through each library and updating it so the various macros used to define the interfaces are correctly represented in clj-kondo.#2021-11-2417:09chrisnWhat is the relationship between emacs lsp-mode and clojure-lsp?#2021-11-2417:09chrisnWell, and clj-kondo.lsp?#2021-11-2417:18borkdudelsp-mode is the emacs lsp client#2021-11-2417:18borkdudeclojure-lsp is the clojure lsp server#2021-11-2417:18borkdudeand clj-kondo.lsp is an lsp server which only provides clj-kondo and nothing else#2021-11-2417:19borkdudeif you use clojure-lsp, you don't need to install clj-kondo or use clj-kondo.lsp#2021-11-2417:21chrisnPerfect, this all makes sense. Thanks everyone (bork, eric, derek) for the help.#2021-11-2422:28ericdalloIs it possible to return a valid :keywords analysis for this code 🧵 ?#2021-11-2422:28ericdallo
(ns test-ns
  (:require
   [xtdb.api :as xt]))

::xt/
#2021-11-2422:29ericdallokondo return the analysis for all other things like namespaces and requires, but I'd like a keyword analysis element for ::xt/ , even if is not correct, I'd like to know easily the namespace from that alias#2021-11-2422:30ericdallothis is already possible for ::xt/anything , but not when the code is invalid#2021-11-2422:30ericdallothis is useful to show to users completion items when they just ask for ::xt/ , to show all available :reg keywords on that namespace. Related issue: https://github.com/clojure-lsp/clojure-lsp/issues/649#2021-11-2422:49borkdudeFeel free to post an issue#2021-11-2515:37orestisIs there a known issue with macros in ClojureScript code? I get warnings about unresolved vars whenever I use a macro that comes from a cljs namespace but is defined in a clj namespace. #2021-11-2515:41borkdude"that comes from", do you mean "used in"?#2021-11-2515:43orestisThe macro is defined in foo.clj, there's also a foo.cljs and the consuming code is at bar.cljs#2021-11-2515:44borkdudecan you make a small repro that I can clone and lint?#2021-11-2515:44orestisThere's a special invocation that I forget that makes this work #2021-11-2515:45orestisSure, I'm on my mobile but I will try later tonight. Three separate files or does a text block here work?#2021-11-2515:45borkdude> that I can clone and lint? #2021-11-2716:32orestisTurns out I can't reproduce. Might have been some cache issue on my local repo....#2021-11-2515:46borkdude🙏#2021-11-2515:52orestisThe case I have in mind is https://clojurescript.org/guides/ns-forms#_implicit_sugar but I will also make a repro later #2021-11-2520:59Jacob RosenzweigIs there a way to force clj-kondo in vscode to resolve macros from a dep that it just doesn't want to load?#2021-11-2521:00borkdudewhat is "it" in your question, clj-kondo?#2021-11-2521:02Jacob RosenzweigThe default clojure plugin for VSCode.#2021-11-2521:04borkdudeYou can probably solve this with {:lint-as {play-clj.core/defscreen clj-kondo.lint-as/def-catch-all}}in your clj-kondo config#2021-11-2521:06borkdudeAlso see https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#unrecognized-macros#2021-11-2521:09Jacob RosenzweigOh stupid, I have the wrong root folder opened.#2021-11-2521:09Jacob RosenzweigBut yes, that's unrecognized macros function is neat. Thanks for that nugget.#2021-11-2521:02Jacob RosenzweigNow that I think about it, it could even just be the linter itself bugging out. Though it shows a clj-kondo error when I hover over it.#2021-11-2522:30borkdudehttps://twitter.com/borkdude/status/1463997962187685890#2021-11-2619:00chrisnGetting this error while linting datatype.clj :
src/tech/v3/datatype.clj:167:19: error: Unresolved symbol: idx
src/tech/v3/datatype.clj:167:19: warning: Unresolved namespace hooks.datatype. Are you missing a require?
That hooks.datatype file does exist: https://github.com/cnuernber/dtype-next/tree/clj-kondo-builtin/resources/clj-kondo.exports/cnuernber/dtype-next
#2021-11-2619:01chrisncmd line I am using is https://github.com/cnuernber/dtype-next/blob/clj-kondo-builtin/scripts/clj-kondo.#2021-11-2619:02borkdude
src/tech/v3/datatype.clj:167:19: warning: Unresolved namespace hooks.datatype. Are you missing a require?
This warning just means that you're using the namespace without having required it.
#2021-11-2619:04borkdudeProbably your hook is generating some code with this name in it?#2021-11-2619:05borkdudeYeah that's the issue. Your macro is defined in a namespace hooks.*. I recommend renaming this namespace to the same namespace as where the original namespace is occurring.#2021-11-2619:06borkdudeIt's recommended for exported config hook code to use unique namespaces anyway and the convention is <org>/your_lib/file.clj or so, similar to how you would do it in your lib#2021-11-2619:11borkdude^ @chris441#2021-11-2619:22chrisnI put the config file exactly there, cnuernber/dtype-next/config.edn. Then it will have an entry that is {:macroexpand {tech.v3.datatype/make-reader tech.v3.datatype/make-reader}} with the code under resources/clj-kondo.exports/cnuernber/dtype-next/tech/v3/datatype.clj. Is that the recommendation?#2021-11-2619:24chrisnAlso, I have a few namespaces that simply extend protocols but aren't used directly in the file. Is there a good way to annotate those namespaces or the require itself?#2021-11-2619:25borkdudeyeah#2021-11-2619:25borkdude(to the first question)#2021-11-2619:26borkdudeI don't understand the need for "annoting those namespaces".#2021-11-2619:26borkdudeCan you clarify with an example?#2021-11-2619:27chrisn
(ns a.b.c
  (:require [protocol-defs :as pdef]
            [protocol-impls]))

(defs/use-protocol :a)  
#2021-11-2619:29chrisnSomething like there where there are protocol or multimethod implementations but the namespace doesn't export anything aside from that.#2021-11-2619:31borkdudeI still don't understand. What is the problem?#2021-11-2619:32chrisnunused namespace warning#2021-11-2619:32borkdudebecause you're not using pdef?#2021-11-2619:33borkdudeif you don't add an alias then clj-kondo will assume you are requiring only for side effects#2021-11-2619:33chrisnAh, ok, there it is. The times I have seen it I had an alias, sorry, that clears it up.#2021-11-2619:33borkdudegotcha#2021-11-2716:30chrisnIs there a recommended way to both develop exported configs and have per-library configs for internal symbols? My attempt so far - that didnt' work, is to add config-paths to the .clj-kondo/config.edn file as such:
{:config-paths ["resources/clj-kondo.exports/cnuernber/dtype-next/"]}
When I use --config-path as a command line arg using the above path it works, but if I don't provide any command line args it doesn't work - I expected the command line pathway to respect the config-paths in config.edn.
#2021-11-2716:32borkdude@chris441 that's almost the right config, just add ../ in front of that#2021-11-2716:32borkdudeand remove the trailing /#2021-11-2716:33borkdudethe config-paths are always relative to the config.edn#2021-11-2716:33chrisnperfect - it worked great. Thanks!#2021-11-2802:04Lukas Domagalai’m having problems with the kondo cache, it seems running with :cache true and false takes the same amount of time and deleting using a different :cache-dir doesn’t change the time either#2021-11-2807:56borkdudeCan you be more specific about what the actual problem is you’re experiencing @domagala.lukas ? The cache is used to get information about other namespaces while linting in your editor. It’s not a performance thing. But you can skip linting already linter deps using the dash dash dependencies flag.#2021-11-2809:31Lukas Domagala@U04V15CAJ i’m running it through
clj-kondo/run! {:cache-dir ".kondo/.cache"
                                       :parallel true
                                       :cache true
                                       :lint files
                                       :config {:output {:analysis true}}})
i need the analysis, but dont really care aboute the linting part since its in process with the source anyway + i’ve got lsp running with a second analysis. i was hoping i could share the kondo cache that lsp’s running version produces to make my in process one faster
#2021-11-2809:50borkdude@domagala.lukas What kind of files are you linting. Just normal source files or .jar files?#2021-11-2810:49Lukas Domagala@U04V15CAJ both. i’m basically using kondo as a dependency analyzer for function calls to get a deep call graph#2021-11-2810:53Lukas Domagalaif you’re interested in the exact usecase: https://github.com/Cyrik/omni-trace currently working on a feature that lets you make a function call that automatically instruments the call graph, but only that and then removes the instrumentation right after the call. i don’t want to search for the dependencies myself though, since you already did the work for me :)#2021-11-2811:00borkdude@domagala.lukas clj-kondo skips dependencies it already linted with :dependencies true . But it doesn't return analysis for those dependencies it skipped. You need to implement your own caching in this case. Just save the analysis information of previously analyzed files somewhere and then combine it with the new analysis.#2021-11-2811:00borkdudeThis is what LSP itself is also doing.#2021-11-2811:01borkdudeI think you don't even need to lint all the jars every time if you do that, just lint the source the user changed.#2021-11-2811:05Lukas Domagalayeah that’s what lsp is doing and saving it as a datalevin file, I just didn’t want datalevin as a dependency. was hoping kondo’s cache did the same thing. but yeah you are right, i’ll just do it the same way lsp does it and save it as plain edn. is there a way to run the analysis without running the linting part, since i don’t use that info anyway? or wouldn’t that change much about the run time anyway? thanks for the help btw#2021-11-2811:09borkdudeit wouldn't change much#2021-11-2811:09borkdudebut you can turn it off by replacing all linters with level off:
:config {:linters ^:replace {}}
#2021-11-2823:22chrisnI think I am stuck on an important macro used in several downstream libraries. • https://github.com/cnuernber/dtype-next/blob/master/src/tech/v3/datatype/export_symbols.cljhttps://github.com/cnuernber/dtype-next/blob/clj-kondo-builtin/resources/clj-kondo.exports/cnuernber/dtype-next/tech/v3/datatype/export_symbols.clj#L3#2021-11-2823:24chrisnWhen I look at the transit-json data, the exported symbols are there but they lack the correct function arities and the documentation.#2021-11-2823:26chrisnLess important they also lack the correct links to the actual source files. For example, from the repl, this is the metadata of https://github.com/cnuernber/dtype-next/blob/clj-kondo-builtin/src/tech/v3/datatype.clj#L49reader>:
user> (require '[tech.v3.datatype :as dtype])
nil
user> (meta #'tech.v3.datatype/->reader)
{:line 146,
 :column 1,
 :file "tech/v3/datatype/base.clj",
 :name ->reader,
 :ns #namespace[tech.v3.datatype],
 :doc
 "If this object has a read-only or read-write conversion to a buffer\n  object return the buffer object.  Else throw an exception.",
 :arglists ([item] [item read-datatype])}
#2021-11-2823:27chrisnThe file, line, column inforrmation allows emacs/cider based pathways to find the correct true definition.#2021-11-2823:28chrisnThis gets into the heart of something I was curious about - when does clj-kondo actually load a required file and can I get to the actual namespace definitions in another source code file, not in some definition under .clj-kondo/...#2021-11-2823:28chrisnClearly it does both.#2021-11-2910:33borkdude@chris441 For this purpose we have ns-analysis: it will return cached data. Clj-kondo does not read anything from disk while linting. It just lints the fileset you give it. But if you already have linted your files once, then ns-analysis gives back the vars for a certain namespace. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md.#2021-11-2910:35borkdudeNote that requiring-resolve etc in a clj-kondo macro (at "compile" time) just loads other hook code, it doesn't load your real dependency.#2021-11-2916:34chrisnThat is what I figured after looking at the data. Thanks, will checkout hooks a bit closer.#2021-11-2916:41borkdudeI think @hugod had a very similar use case like yours, this is why ns-analysis got added#2021-11-2916:45hugodUsing ns-analysis works well when using clojure-lsp, since it is generally kept from getting stale. I’ve used it for impprt-ns type macros, and also for some macros that import defrecord types.#2021-11-2916:46borkdudeIt should also work with vanilla flycheck-clj-kondo etc, every time you visit the imported ns and change stuff there, the analysis cache is updated. If you're thinking of switching branches, then you could make a commit hook to re-lint your project.#2021-11-2916:46borkdudeBut clojure-lsp also takes care of that
#2021-11-2922:04chrisnOK, that appears to be working in one sense - the errors I get out of clj-kondo now match the correct arities of the imported functions.#2021-11-2922:06chrisnWhen I load the actual metadata produced, however, I note that the imported functions don't have a :fixed-arities map entry - I am careful to recreate the arities in the macro -
(defmacro export-symbols
  [src-ns & symbol-list]
  (let [analysis (:clj (hooks-api/ns-analysis src-ns))]
    `(do
       
So I would say this is perhaps finished or perhaps just partly working. I don't see argnames anywhere which is fine nor a docstring but I didn't see that in the metadata before so perhaps also fine.
#2021-11-3000:32hugodThis is what I have
(defn import-namespace
  "Transform an import-ns into a sequence defn and defmacro"
  [{:keys [node]}]
  (let [[_ ns-name] (:children node)
        analysis    (-> (:string-value ns-name)
                        symbol
                        api/ns-analysis
                        :clj
                        vals)
        new-node
        (api/list-node
         (list*
          (api/token-node 'do)
          (->> analysis
               (remove :private)
               (mapv
                (fn
                  [{:keys [fixed-arities
                           macro
                           varargs-min-arity]
                    sym   :name}]
                  (if (or fixed-arities varargs-min-arity)
                    (api/list-node
                     (list*
                      (if macro
                        (api/token-node 'defmacro)
                        (api/token-node 'defn))
                      (api/token-node sym)
                      (if fixed-arities
                        (map
                         (fn [n]
                           (api/list-node
                            (list
                             (api/vector-node
                              (repeat n (api/token-node '_)))
                             (api/token-node
                              (symbol
                               (:string-value ns-name)
                               (str sym))))))
                         fixed-arities)
                        [(api/vector-node
                          (concat
                           (repeat varargs-min-arity (api/token-node '_))
                           [(api/token-node '&) (api/token-node '_)]))
                         (api/token-node
                          (symbol
                           (:string-value ns-name)
                           (str sym)))])))
                    (api/list-node
                     (list
                      (api/token-node 'def)
                      (api/token-node sym)
                      (api/token-node
                       (symbol
                        (:string-value ns-name)
                        (str sym)))))))))))]
    #_(prn :import-namespace (api/sexpr new-node))
    {:node (with-meta new-node (meta node))}))
#2021-11-2922:08borkdudeYou can look in the transit map in the .cache folder to see if the info is there. Perhaps it's just not exposed currently.#2021-11-2922:10chrisnI am looking at the transit map. Here is the metadata of the source function:
{->reader
 {:row 146,
  :col 1,
  :fixed-arities #{1 2},
  :name ->reader,
  :ns tech.v3.datatype.base,
  :top-ns tech.v3.datatype.base},
and here is the metadata of the imported function:
{->reader
 {:row 40, :col 1, :name ->reader, :ns tech.v3.datatype, :top-ns tech.v3.datatype},
Now as I said above, clj-kondo is itself reporting arity issues correctly with the function so at runtime it is correct I am just curious about the metadata as my goal is for clojure-lsp to work correctly with this.
#2021-11-2922:11borkdudeAccording to the code it should be there: https://github.com/clj-kondo/clj-kondo/commit/e69702bc548625e190b762d130a4a21753da993a#diff-e170b652b1781fe9cad415205220a92f520f94f3c896160a3126e63e5b935694R73#2021-11-2922:12borkdudehmm#2021-11-2922:12chrisnAh, it is in the function expansion. clj-kondo lints to code correclty:#2021-11-2922:12chrisn
(base) 
#2021-11-2922:13chrisnIt just didn't make it to the metadata cache itself#2021-11-2922:13chrisnOr the cache didn't update or I am looking at the wrong cache.#2021-11-2922:14borkdudeclj-kondo command line may be a different version than what lsp uses (typically a recent snapshot)#2021-11-2922:14borkdudeand each version of clj-kondo caches under its own key#2021-11-2922:15borkdudein the .cache dir: .cache/$version/...#2021-11-2922:15chrisnGot it, that makes sense.#2021-11-2922:15chrisnI was looking at the wrong cache.#2021-11-2922:16chrisnclj-kondo's cache is now correct.#2021-11-3013:10tatutan idea, could linter warn about using case with Java enums like
(let [x java.util.concurrent.TimeUnit/SECONDS]
  (case x
    java.util.concurrent.TimeUnit/SECONDS "secs"
    java.util.concurrent.TimeUnit/MINUTES "mins"))
^ will cause "No matching clause" at runtime as case works with compile time literals... idk if this would be annoying when you actually do want to compare against symbols
#2021-11-3013:24borkdudehow should clj-kondo know you're not actually matching against real symbols here?#2021-11-3013:26tatutyeah, I see that's one issue#2021-11-3013:28tatutI'd usually use keywords instead of symbols, but for me I'd say if the symbol matches an enum pattern some.Class/ENUM_VAL but that would perhaps be too opinionated as a general rule#2021-11-3014:45Noah Bogartwould a type hint be usable here?#2021-11-3014:46Noah Bogart(let [^java.util.concurrent.TimeUnit x java.util.concurrent.TimeUnit/SECONDS] (case x …)) would then carry the “enum type” on x#2021-11-3014:46Noah Bogartit’s quite ugly lol but maybe clj-kondo could use it?#2021-12-0100:47Noah BogartI’m starting to work with #re-frame. The various event and subscription functions (`re-frame/reg-event-db`, etc) accept a function (usually an anonymous function) that take a regular set of inputs. Would it be possible to write a lint that requires certain function parameters to have specified names?#2021-12-0113:28borkdudeCan you give an example of this?#2021-12-0113:29borkdudeBut yes, I think that is possible#2021-12-0114:25Noah Bogartexample from here: https://day8.github.io/re-frame/subscriptions/#reg-sub
(re-frame.core/reg-sub
  :id
  (fn [db query-v]
    (:something db)))
in the simplest usage, re-frame.core/reg-sub takes a keyword and a function (binding the function to the keyword in a hidden global state like s/def). the function must accept a hashmap and a vector. I’d like to specify that the hashmap always be named db.
#2021-12-0114:27Noah Bogartthis will keep all of the reg-sub calls consistent and make writing the handling functions more clear (instead of potentially having one be db and another be app-db and a third be m)#2021-12-0122:19borkdude@UEENNMX0T Yes, you can write a hook for this#2021-12-0119:24chrisnLast issue I think - For the ffi system, I define the functions with datastructures and then use these to generate functions in the namespace:#2021-12-0119:24chrisnhttps://github.com/cnuernber/dtype-next/blob/clj-kondo-builtin/src/tech/v3/datatype/ffi.clj#L811#2021-12-0119:25chrisnIn the above example, clj-kondo complains about memset not being defined.#2021-12-0119:26chrisnI attempted a macro expansion of define-library-functions! but this could not use the data in the symbol - I had to use (resolve sym-name) in the macro in order to do this in Clojure and when sci is running the macro I can't resolve that variable like that.#2021-12-0119:31chrisnOne solution would be to collapse that all into one macro instead of a few macros. Then I could pass in the datastructure to the macro itself.#2021-12-0119:31chrisnAnd hope users define it explicitly.#2021-12-0119:32borkdude@chris441 what would you need in the hook, a helper function or more data?#2021-12-0119:37chrisnI run through each function and define it with the appropriate args in the macro#2021-12-0119:39borkdudeI don't understand the issue#2021-12-0119:44chrisnOk, out of time - will explain further#2021-12-0119:53borkdudeclj-kondo 2021.12.01  • Improve linting in `extend-protocol`, `extend-type`, `reify`, `specify!` https://github.com/clj-kondo/clj-kondo/issues/1333https://github.com/clj-kondo/clj-kondo/issues/1447 • Support `:context` in nodes in hooks for adding context to analysis https://github.com/clj-kondo/clj-kondo/issues/1211goog.object, `goog.string` etc must be required before use in newer releases of CLJS https://github.com/clj-kondo/clj-kondo/issues/1422 • Resume linting after invalid keyword https://github.com/clj-kondo/clj-kondo/issues/1451 • Fix install script for relative dir opts https://github.com/clj-kondo/clj-kondo/issues/1444 • Fix type mismatch error with auto-qualified keyword https://github.com/clj-kondo/clj-kondo/issues/1467 • String type hint causes false error report https://github.com/clj-kondo/clj-kondo/issues/1455 • Fix false positive with cljs/specify! https://github.com/clj-kondo/clj-kondo/issues/1450 • Improve analysis for ns-modifying destructuring key https://github.com/clj-kondo/clj-kondo/issues/1441 • CLJS `(exists? foo.bar/az)` complains about require https://github.com/clj-kondo/clj-kondo/issues/1472 #2021-12-0211:36Adam HelinsUsing GitlabCI, my lint job fails once in a while (not very often at all):
$ clj-kondo --parallel --lint src test
test/salus/server/fixtures/citizen.clj:66:29: error: Attempting to call unbound fn: #'hooks.salus.server/with-serializable-txn
What is odd is that there are other hooks defined in the same file, yet I only get this error for that particular one (last defined), and it's not systematic at all. Any idea?
#2021-12-0211:36borkdude@adam678 which version of clj-kondo is this?#2021-12-0211:37borkdudeThere was a bug once when you used --parallel because the require stuff in SCI isn't thread-safe#2021-12-0211:39Adam HelinsLooks like it's still 2021.03.31 in the Nix env#2021-12-0211:39borkdudeyeah, that's probably it then. upgrading it should fix it#2021-12-0217:53chrisnWhen importing dependencies, do you have to import twice perhaps when your macros rely on files that haven't been cached yet?#2021-12-0217:56chrisnThe reason ns-analysis returns nil if the file hasn't been cached yet I gather. In any case, once I got dtype-next working correctly in its own project I moved to avclj, ran the --config --dependencies cmd to generate them and none of the imported definitions are present in the metadata.#2021-12-0218:02chrisnIs there a way to re-run the linter, forcing it to regenerate the cache?#2021-12-0218:05chrisnremoving the skip directory in the cache caused clj-kondo to re-run thus picking up the definitions that relied on ns-analysis to work. If I require the namespaces at the top level without an alias will that cause them to be linted before this namespace and thus cause the caching mechanism to work correctly the first time?#2021-12-0218:07robert-stuttafordi have this in my .zshrc, @chris441
rekondo () {
  rm -rf .clj-kondo/.cache/ && clj-kondo --lint "$(clojure -Spath)" --parallel
}
#2021-12-0218:08robert-stuttafordjust as a really blunt "let's start all this again, shall weeee?" button#2021-12-0218:09chrisnThat is helpful but removing the entire cache won't work. I have macros that import definitons from other namespaces that rely on clj-kondo's ns-analysis api which itself relies on the file being cached already. If it is not -as is what happens on first run, then ns-analysis returns nil and the linter macro incorrectly fails to define the functions. If I run the linter, thus creating the data namespaces and then remove only the skip dir and run again it produces the right answer.#2021-12-0218:10chrisnThis also is causing clojure-lsp to fail to lint correctly so I need a more thorough fix I think.#2021-12-0218:14chrisnIt is specifically an issue with the order that clj-kondo lints to source tree.#2021-12-0218:58borkdude@chris441 I agree that we should somehow improve this, at least within one library / dependency. Perhaps with a tools.namespace dependency like approach.#2021-12-0218:58borkdudeSo far it hasn't been much of a problem, but with hooks that need pre-cached analysis it is.#2021-12-0219:02borkdudeI'll make an issue for this#2021-12-0219:02borkdudeand prioritize it#2021-12-0219:05borkdudeHowever, this is another challenge. The cache is not read or written to while linting, this is only done at the very end.#2021-12-0219:06borkdudebut perhaps ns-analysis can be made so that it also reads from the in-memory results (so far)#2021-12-0219:07borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1476#2021-12-0219:09borkdude@chris441 if you tell me how I can test this out with your project in the above issue, that would help#2021-12-0219:17chrisn@borkdude - I really appreciate your support a lot but thinking this through I think a better design for my project is to use code generation to generate the api .clj files. Even if we work through these issues I still don't support Cursive and I feel like this is perhaps not worth changing clj-kondo for and no matter what would still get a partial result. So let's pause on this and I will investigate implementing code generation on top of the existing api files, just renamed. Perhaps it isn't necessary to solve this issue for this reason at this time.#2021-12-0219:19borkdude@chris441 Makes sense. Code generation is always a way out.#2021-12-0219:20borkdudeWe've recently created a stub library to create stubs for closed sources like the datomic API. This also helps clj-kondo. Cursive / IntelliJ has a similar approach.#2021-12-0220:15chrisnIs that stub library opensource? My current plan is to just call ns-publics, call meta on each one and try to define fns, defs, and macros with correct return type hints.#2021-12-0220:17borkdudeyes: https://github.com/clj-easy/stub#2021-12-0319:44chrisnCodegen worked. I tested everything (both codegen and updated clj-kondo resource hooks) with avclj. For things that are public-api facing, I think codegen hits the widest possible audience. Internal to my libraries, I will now publish clj-kondo hooks with the libraries themselves. Codegen via ns-publics, btw, was https://github.com/cnuernber/dtype-next/blob/master/src/tech/v3/datatype/export_symbols.clj#L72 - and produces https://github.com/cnuernber/dtype-next/blob/master/src/tech/v3/datatype.clj.#2021-12-0319:47borkdudeAwesome! Yes, I think it's the most reliable method.#2021-12-0319:47borkdudeUnless you use something like the potemkin macro which enumerate all the var names explicitly#2021-12-0319:47borkdudeThat one is relatively easy to support via hooks (we already have a built-one for it)#2021-12-0319:48borkdudeBut code-gen surely works and needs nothing extra#2021-12-0413:30amithgeorgeI am thinking of a lint rule. Warn when there are unused inputs in some code paths of a function. Consider this function
(defn scan
  [price display input]
  (if-let [product-id (parse-product-id input)]
    (if-let [product-price (price product-id)]
      (display product-price)
      (display "Not found!"))
    (display "Invalid code!")))
If the parse function returns nil, the code execution moves to calling display with "Invalid code". In this code path, the price input remains unused. Is this something possible with a lint rule?
#2021-12-0413:34borkdudeI suspect that would cause a lot of people to complain about this linter#2021-12-0413:36amithgeorgeI am not very familiar with cljkondo. If there is a way to store lint rules in another library and pass them to cljkondo via config, I would very much love to build/use such a lint rule.#2021-12-0413:36amithgeorgeIs such a rule even possible with current capabilities of clj-kondo?#2021-12-0413:36borkdudeIt is possible to build rules for certain function calls#2021-12-0413:37borkdudeSee https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2021-12-0413:37borkdudeThis is mostly used to macroexpand custom macros#2021-12-0413:37borkdudeBut you can use it for purposes of linting bodies of function calls too#2021-12-0413:42amithgeorgeFrom an initial skim of the document, it sounds like I have to register my custom code for every function I wish it to be executed against. In my scenario scan was one function where the issue was demonstrated. I would ideally like to lint/check every (as many as needed) function.#2021-12-0413:47borkdude@U0A5B1LJU In your case, I recommend to make a fork of clj-kondo to experiment and see how useful your linting rule becomes.#2021-12-0413:47borkdudeAnd then you could raise an issue and explain in more detail why you would want to contribute that back#2021-12-0413:48borkdudeIn the case of your linting rule, I expect this would be "too much" for most people, it is very common to not use all arguments in all branches#2021-12-0413:48amithgeorgeI noticed this section https://github.com/clj-kondo/clj-kondo/tree/master/analysis#analysis-data-and-tools ... is that a viable option? or forking is more viable?#2021-12-0413:48borkdudein the analysis data you can access all locals#2021-12-0413:49borkdudewhere they are introduced, their scope and where their usages occur#2021-12-0413:49borkdudebut you cannot see if they are in the left or right side of an if for example (I think)#2021-12-0413:51amithgeorge> I expect this would be "too much" for most people, it is very common to not use all arguments in all branches True. Even I am not sure how useful it will be. It is an experiment for me.#2021-12-0413:52borkdudeI think what you can do with the analysis: You know the scope of each local You know the locations of each usage of the local You know the scope of each var usage (function call)#2021-12-0413:52borkdudeThen you can decide if there are function calls within the scope of a local that have no local usages#2021-12-0413:53borkdudebut this will also catch:
(let [x 1]
  (prn x)
  (prn :hello) ;; no usage)
#2021-12-0413:53borkdudeso you kind of have to know if you are a direct child of a conditional#2021-12-0413:54borkdudeand then you would have sufficient data to calculate this#2021-12-0413:54borkdudewe could try to add that to the analysis data, if that turns out to be useful#2021-12-0413:56borkdudeclj-kondo actually already has a callstack like thing#2021-12-0413:56borkdudewhich we could just include in the analysis#2021-12-0413:56borkdudebut for now, do it in a fork#2021-12-0413:56amithgeorgeWould supporting the kind of linter we are theorizing , be a valid reason to augment the analysis data 🙏#2021-12-0413:56borkdudefor experimentation#2021-12-0413:57borkdudeit's a chicken and egg problem: you don't know if it's worth adding until you know that what you added it for is useful enough#2021-12-0413:57borkdudeso a fork is best#2021-12-0413:58amithgeorgeThanks a lot. This is helpful. It will take me a while to understand the code enough to build this. It will be interesting for me to do though 🙂 Will ping in the channel when I need help. Thanks again.#2021-12-0419:49chrisnI moved on to working on tech.ml.dataset and I reduced the linting issues down to just a few things that are difficult to reduce further.
(graal-native/when-not-defined-graal-native
 (require '[clojure.pprint :as pprint])
 (defmethod pprint/simple-dispatch
   tech.v3.dataset.impl.dataset.Dataset [f] (pr f))) 
I use that to keep pprint out of graal native. That simple-dispatch is required for some editors to correctly print a dataset. It produces the warning:
src/tech/v3/dataset/impl/dataset.clj:452:13: warning: Unresolved namespace pprint. Are you missing a require?
Next -
(definterface PParser
  (addValue [^long idx value])
  (finalize [^long rowcount]))
This produces a warning -
src/tech/v3/dataset/io/column_parsers.clj:132:20: warning: unused binding rowcount
Next I have a file with a complex macro system so I can efficiently bind the many and varied arrow https://github.com/techascent/tech.ml.dataset/blob/master/src/tech/v3/libs/arrow/datatype.clj. I would like to exclude this file entirely from processing.
#2021-12-0419:50borkdude@chris441 I think this would work:
{:lint-as {graal-native/when-not-defined-graal-native clojure.core/comment}}
#2021-12-0419:51borkdude(you need to fully qualify the namespace on the left hand side as well)#2021-12-0419:51chrisnclj-kondo lints my comments.#2021-12-0419:52borkdudeyes, then you're good, since it will see that require as a top level thing#2021-12-0419:52borkdudeor probably clojure.core/do is better#2021-12-0419:52borkdudesince some people turn off linting for comment#2021-12-0419:53borkdudeYou can exclude a file with {:output {:exclude-files ...}}#2021-12-0419:53borkdudeit will still process them though, just not show lint warnings about them#2021-12-0419:53borkdudethis should be better supported#2021-12-0419:53chrisnno dice, it still caused the error.#2021-12-0419:55borkdudecan you post a github issue with a repro about each thing?#2021-12-0419:55borkdudeor just a repository, issue not needed yet#2021-12-0419:55borkdudethen I can test it locally#2021-12-0419:55borkdudeand provide better advice#2021-12-0419:56borkdudeif you can tell me how to lint that locally#2021-12-0419:57chrisnhttps://github.com/techascent/tech.ml.dataset/ - master branch - scripts/clj-kondo#2021-12-0419:58chrisnI added a config to turn comments off. This combined with the graal-macro-as-comment pathway worked for two of them.#2021-12-0419:58chrisnDown to 2, from I think about 500.#2021-12-0420:00chrisnAgain, I would be interested in being able to exclude files either in config.edn or in a bit of namespace metadata from linting altogether. I don't think supporting complex macro systems that are used purely to compress implementation is worth it.#2021-12-0420:02borkdudeI get zero errors on that master branch#2021-12-0420:03borkdude> linting took 979ms, errors: 0, warnings: 232#2021-12-0420:06borkdude@chris441 can you provide some more specific things that you're not satisfied with?#2021-12-0420:07chrisnSorry, I am right now checking into master a cleanup. One sec.#2021-12-0420:08chrisn(base) /cdn-cgi/l/email-protection:~/dev/tech.all/tech.ml.dataset$ gpush To http://github.com:techascent/tech.ml.dataset b6f9f4e..e3fca12 master -> master (base) /cdn-cgi/l/email-protection:~/dev/tech.all/tech.ml.dataset$ scripts/clj-kondo src/tech/v3/dataset/io/column_parsers.clj:132:20: warning: unused binding rowcount src/tech/v3/libs/arrow/datatype.clj:15:13: warning: Unused import TimeStampMilliTZVector linting took 969ms, errors: 0, warnings: 2#2021-12-0420:09chrisnlol, -- not asking you to look into hundreds of warnings!#2021-12-0420:10borkdude😅#2021-12-0420:10borkdudeI'm now getting: > linting took 1106ms, errors: 0, warnings: 232#2021-12-0420:10borkdudeon branch master#2021-12-0420:11borkdudebtw, this config is not correct:
:config-path ["cnuernber/dtype-next"]
#2021-12-0420:11borkdudeit should be: :config-paths#2021-12-0420:18chrisnDone. Now I get a few more warnings but not many.#2021-12-0420:18borkdudeAlso I recommend checking in the config for cneurber/dtype-next into the .clj-kondo dir#2021-12-0420:19borkdudeso everyone who clones the repo can use the config straight away#2021-12-0420:19chrisnmakes sense.#2021-12-0420:32chrisnbtw- I am super happy with where this ended up. I get a bit more robustness, linting, and discoverability across every clojure editor as a result of the whole process. Thanks for the help so far - will definitely shout it out.#2021-12-0420:33borkdudecool :) I lost track of what the remaining issue is#2021-12-0420:34chrisndefinterface produces spurious rowcount warning.#2021-12-0420:34chrisnThat would be one. The second is being able to skip linting for a particular file via config.#2021-12-0420:36borkdudeHave you tried
{:output {:exclude-files ["regex/for/file.clj"]}}
#2021-12-0420:52borkdudeAbout the definterface one: I think that's a bug in clj-kondo, please file an issue#2021-12-0420:53borkdudeyou can temporarily put a #_:clj-kondo/ignore before the form to ignore the warning#2021-12-0617:49dpsuttonAn error I just caught in a PR (and simplified into obvious small case)
(let [strings (filter string? (range 23))]
  (when strings
    (println "i found strings")))
The intention here is when strings are found, but the empty lazy seq returned from the filter is always truthy. I know clj-kondo has some type-inference going on. Is it possible for it to catch this error?
#2021-12-0618:17borkdude@dpsutton It doesn't currently have this but I love that idea.#2021-12-0618:17dpsuttoncool. i’ll make an issue then. wasn’t sure if it was something you had enough info to work with at all. glad to know#2021-12-0618:38borkdudeI think I saw this issue before in the recent days when I went through all of them, and yes, here it is: https://github.com/clj-kondo/clj-kondo/issues/721 Give it a thumbs up.#2021-12-0618:42dpsuttoni added the edge case i could think of and a thumbs up. Thanks @borkdude#2021-12-0708:37borkdudebetter-cond users rejoice! there is now a config as part of the library, https://twitter.com/borkdude/status/1468137387624648707#2021-12-0810:40lassemaattaif I have a fn-like macro, which introduces a symbol within the scope of the body, I can use :unresolved-symbol to tell clj-kondo to exclude the symbol. But what if I have a macro, which uses a binding from the outer scope from the call site? Naturally clj-kondo doesn't know that the macro uses the binding and I will (assuming no one else uses it) get an unused binding warning.#2021-12-0810:42borkdude@lasse.olavi.maatta can you sketch an example of what the usage looks like?#2021-12-0810:44lassemaatta#2021-12-0810:45lassemaatta(don't ask me why someone wrote a macro like that..)#2021-12-0810:46borkdudeI would rewrite this macro to take the a binding explicitly#2021-12-0810:46borkdudeor make another arity which does that, to keep compatibility with the old callers#2021-12-0810:47borkdudeor you can make a wrapper macro which does that#2021-12-0810:48borkdudeif this is not possible, then you can write a hook to expand the some-macro into code which does use the a binding#2021-12-0810:48borkdudesee https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand#2021-12-0810:48lassemaattayeah, there's probably plenty of ways to fix the original code#2021-12-0810:49lassemaattathanks#2021-12-0909:48joost-diepenmaatI just filed a PR but one of the tests on CI fails and I’m not sure if it’s my code or something unrelated. https://app.circleci.com/pipelines/github/clj-kondo/clj-kondo/4076/workflows/1aca8e2a-61cc-4e40-951e-5b8380f42b9d/jobs/16417#2021-12-0909:48joost-diepenmaatTests run all find locally when doing script/test#2021-12-0909:48borkdudeIt seems to be unrelated. Thanks, I'll take a look hopefully soon#2021-12-0909:49joost-diepenmaatOk, if it looks related I’ll take another look. Now off to do work that pays the bills 🙂#2021-12-0913:00roman01la👋 What's the debugging strategy when running linters through LSP jar? I have a linter that works via CLI but warnings are not appearing in Cursive. I guess clj-kondo should be storing logs somewhere?#2021-12-0913:03borkdudeAre you using clj-kondo with clojure-lsp in Cursive or otherwise?#2021-12-0913:03roman01la@borkdude Hey, no clojure-lsp, but kondo's LSP JAR#2021-12-0913:04borkdudeok, I see. are you using the same version on the command line and LSP jar?#2021-12-0913:04roman01laThanks for creating the library btw 🙏 I'm working on linters for React hooks at Pitch. No promises, but will try to publish the linter when it's done and tested.#2021-12-0913:05roman01la> ok, I see. are you using the same version on the command line and LSP jar? uh, good question, let me check#2021-12-0913:10roman01laalright, now I'm running both LSP and CLI of the same version, CLI works, LSP doesn't 😞 is there a way to get into logs?#2021-12-0913:13borkdudeI'm not sure if it logs anything interesting, but the source is here: https://github.com/clj-kondo/clj-kondo.lsp You can build the uberjar yourself and stick some logging in there#2021-12-0913:13borkdudeIf you run bb tasks with babashka, you can see all tasks that are possible in this project#2021-12-0913:14roman01lathanks 🙏#2021-12-0913:14borkdudeThe one you want to have is bb lsp-jar#2021-12-0913:19roman01labtw, I'd love to have all predicates for all clj-rewrite token types (`vector-node?` etc) to be exposed in SCI env when running hooks. Doesn't seem like there's a way to extend SCI config, would you accept a PR for that? (to include more predicates)#2021-12-0913:19borkdudeyes, let's add them one by one though, because not all of them are obvious#2021-12-0913:20borkdudeopen an issue, then followed by a PR. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/dev.md#workflow for workflow#2021-12-0913:20roman01laThis is my ducky workaround for now 😄 (= (str (type f)) "class clj_kondo.impl.rewrite_clj.node.fn.FnNode")#2021-12-0913:21borkdudeomg... ;)#2021-12-0913:23roman01laquick feedback: :__dangerously-allow-string-hooks__ option is great when developing linters in REPL#2021-12-0913:24borkdudeyes, this is what I added it for#2021-12-0913:24borkdudealso for tests#2021-12-0913:25roman01laI've also tried writing hooks in a separate file first, but seems like kondo is not picking up changes, perhaps caching?#2021-12-0913:27borkdudeoh right, yes, it re-uses the SCI context and if you already loaded the hooks, it won't reload them again.#2021-12-0913:29borkdudeif you run (require '[clj-kondo.impl.hooks] :reload) then it probably will#2021-12-0915:43roman01laok, I got it working, but... 😄api/reg-finding! seem to be ignoring :end-col and :end-row? • warning/error messages are not showing up in a popover when hovering over underlined code (this is working fine with clojure-lsp, but not with clj-kondo lsp 😞)#2021-12-0915:44borkdude🎉 how are you calling reg-finding? can you verify if the end-col and end-row are there to begin with?#2021-12-0915:45borkdudeabout the popover - I'm not sure what clj-kondo.lsp and clojure-lsp are doing differently - is this something you would know about @UKFSJSM38?#2021-12-0915:47ericdallonot really, I can't see anything clojure-lsp is doing diferently about that :thinking_face:#2021-12-0915:48borkdudeperhaps it has to do with end-row / end-col then#2021-12-0915:49ericdallohum, makes sense as the warning needs a end-col and end-row on client side#2021-12-0915:49roman01la> perhaps it has to do with end-row / end-col then what interesting is that the message is not showing up for default linters as well#2021-12-0915:50roman01la#2021-12-0915:50roman01lathis one seem to include end row/col#2021-12-0915:50borkdudemaybe clj-kondo.lsp needs to upgrade the lsp library? it's pretty old probably#2021-12-0915:50borkdudebut this intellij lsp plugin is also pretty old#2021-12-0916:03ericdalloyeah, my guess is the intellij plugin#2021-12-0916:03borkdudebut he uses the same lsp intellij plugin for clojure-lsp?#2021-12-0916:04ericdallooh and does it work for clojure-lsp?#2021-12-0916:04roman01lawait...#2021-12-0916:04roman01lanah it doesn't, I've double checked#2021-12-0916:04roman01lano message in a popover in both kondo lsp and clojure-lsp#2021-12-0916:05ericdalloyeah, so it sounds like a intellij plugin issues indeed#2021-12-0916:05roman01lagod dammit#2021-12-0916:06ericdalloCome to emacs 😛 Just kidding, unfortunately the intellij lsp plugin is not actively mainted as much as other lsp editors plugins :/#2021-12-0916:06borkdudehttps://github.com/gtache/intellij-lsp#2021-12-0916:07ericdallolast commit was from apr/2020#2021-12-0916:07roman01lahehe, I guess I'll stop writing those linters then#2021-12-0916:08borkdude@U0FR82FU1 you're still writing it for those who use clj-kondo on the command line or in other editors ;)#2021-12-0916:08ericdalloAlthough, clj-kondo is used a lot, for example on clojure-lsp that is used on editors like VScode/emacs/vim#2021-12-0916:09roman01laClojure community really needs more hands to provide a good dev experience#2021-12-0916:09borkdudeIntelliJ just needs better LSP support#2021-12-0916:09roman01lalots of Pitchers are using Cursive, but yeah, could be useful for others and CI as well#2021-12-0916:10ericdalloyeah, besides that, IMO the tools overall are really good for clojure#2021-12-0916:10borkdudeI've also asked @U0567Q30W if he was interested in adding clj-kondo to Cursive, and he was open to that. You can bring this to his attention again.#2021-12-0916:10ericdalloit'd be really good @borkdude for a common lib and configuration 🙏#2021-12-0916:10borkdudeAnd ask in #cursive how other Cursive users are using clj-kondo, there are a few of them#2021-12-0916:11ericdalloat least at nubank, the people who use cursive doesn't just run the lint on the command line and fix it manually :(#2021-12-0916:11ericdalloand for complex macros (that we have clj-kondo config) they just live with that not working on cursive 🥲#2021-12-0916:12ericdallothat's why Nubank is now recommending to new devs using editors with LSP support :)#2021-12-0916:15roman01lagluing everything together is hard#2021-12-0916:15borkdudeperhaps forking the lsp plugin could work - but I can imagine that appears to be a daunting task#2021-12-0916:16borkdudeor making a bespoke intellij plugin for clj-kondo - but I really hope that @U0567Q30W will just add clj-kondo support to Cursive#2021-12-0916:17borkdudeThere is an open source IntelliJ plugin called Clojure-Kit#2021-12-0916:17borkdudewhich could maybe be forked and hacked upon to get diagnostics#2021-12-0916:19borkdude@U0FR82FU1 another thing btw. does CIDER work with intellij - i.e. do CIDER warnings get propagated to intellij as diagnostics?#2021-12-0916:20borkdudethen clj-kondo could maybe work as a cider plugin-ish or so#2021-12-0916:20borkdudeThere must be a light weight way to get clj-kondo working in that environment#2021-12-0916:21roman01laNo idea :woman-shrugging:#2021-12-0916:21borkdudeyou don't use CIDER with intellij?#2021-12-0916:22borkdudethe problem is, I could make an intellij plugin, but I never use it, so it wouldn't be as maintained as when I would use it#2021-12-0916:23roman01lano, I only use what Cursive provides out of the box, now trying with clj-kondo, but no luck so far#2021-12-0916:23borkdude@U0FR82FU1 btw, you can also get clj-kondo running as a github action and it will print diagnostics in the code as feedback#2021-12-0916:23borkdudeso when you push to a branch, this will still help you get feedback#2021-12-0916:24roman01lawe do use it to lint PRs, working great 👌#2021-12-0916:28ericdalloI think @U5B8QSSC9 configured clojure-lsp on intellij, maybe ask if he got the same issue with the popup#2021-12-0916:28ericdalloHe works on Pitch as well :p#2021-12-0916:29borkdude@U0522TWDA I think also uses clj-kondo + Cursive...#2021-12-0916:30roman01latrying with file watcher, seems like it works for others#2021-12-0916:30roman01la@UKFSJSM38 Otto is running it via lsp jar as well 🙂#2021-12-0916:38Jakub Holý (HolyJak)I had some problem with using clj-kondo directly via a file watcher, which I don't remember. And I have given up on Clojure-lsp because the IntelliJ LSP plugin somehow sends many unfounded "file changed" messages in a short time (on my largish project) , which kills my cpu. So I started using kondo via a pre-commit hook.#2021-12-0916:39ericdallo@U0522TWDA clojure-lsp is ATM ignoring those messages so maybe give it another try makes sense?#2021-12-0916:54Jakub Holý (HolyJak)Ah, awesome, thanks! Will try!#2021-12-0916:55roman01ladoesn't work via file watchers at all, lol#2021-12-0916:56roman01laprints something about FILE_PATH is undefined, but ignoring that var doesn't make any difference#2021-12-0916:56roman01laalthough I do see linting output in IDE's console#2021-12-0916:58borkdude@U0FR82FU1 here are some instructions: https://github.com/clj-kondo/clj-kondo/blob/master/doc/editor-integration.md#file-watchers--installed-binary#2021-12-0916:58roman01lathat's what I've followed#2021-12-0917:00borkdude@U06S1EJPL has edited that section a few times - perhaps he knows stuff?#2022-12-2721:09borkdude@U0FR82FU1 I've talked to @UQTHDKJ8J who is the author of a IntelliJ plugin called "Clj Stuff" and it will soon support clj-kondo#2022-12-2721:11ericdalloThat's really good news!#2022-12-2923:02borkdude@U0FR82FU1 https://clojurians.slack.com/archives/CHY97NXE2/p1640817053272400#2021-12-1018:33Noah BogartI want to use the javascript library moment in my code, which i’m using from an npm module. i require it with (ns example (:require [moment])) and then when I use it (-> (:date item) js/Date. moment (.format "MMM Do YYYY")), I get “unresolved symbol: moment” errors. any suggestions on how to write the require such that this is resolved?#2021-12-1018:34borkdude@nbtheduke The solution is to always use strings for npm libs#2021-12-1018:35Noah Bogartoh! huh, cool#2021-12-1203:11emccueis there a way to include camel-snake-kebab for a macroexpand hook?#2021-12-1207:52borkdude@emccue hooks are restricted to core functions and dedicated API functions both for safety and performance. Loading an entire library on each keystroke isn’t going to be performant #2021-12-1207:53borkdudeSo I recommend just implementing that yourself. Java -> kebab style is a one liner #2021-12-1207:57emccueyeah in between then and now i just did so. next issue is the macro is gonna generate some symbols (in the same vein as map->Thing for record) which i dont expect everyone to use, but want to be there. namely a thing? predicate#2021-12-1208:06borkdudeJust generate a do with a def of that symbol #2021-12-1208:07emccuethats smart#2021-12-1417:55ericdalloDoes kondo has built-in support for clojure.test.check.clojure-test/defspec ?#2021-12-1417:55ericdalloI thought it had#2021-12-1418:53mknoszligit would be nice to have support for test.check as a whole if there isn’t already (`prop/for-all` etc as well)#2021-12-1419:31ericdalloI just found it doesn't have, we had a lint-as in our common configuration at nubank#2021-12-1421:21mknoszligthere’s probably a number of things in test.check that could use linting… how about starting with a ticket that defines a minimum viable set of linters to kick it off and then add additional linters one by one later as they come up?#2021-12-1516:17borkdudeJust pushed some new linters to master, among which :unexpected-recur which checks for recur in unexpected places, mostly relevant to non-tail usage of recur. Please take it for a spin and report issues pre-release:
clojure -Sdeps '{:deps {clj-kondo/clj-kondo {:git/url "" :git/sha "2dde61bead4b80d76bbaa505d08c643a5a27e2a8"}}}' -M -m clj-kondo.main --lint src:test
#2021-12-1516:28borkdudeSee here what's new on master: https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#unreleased Several shiny new linters.#2021-12-1519:14borkdudeAlso wanted to mention: if there are any open issues you would like to see solved, you can upvote it with a thumbs up to bump the priority. This will signal that more than one person is interested in the issue being solved and this also enabled sorting the issues by priority.#2021-12-1519:48mknoszligfwiw, i tend to filter by “PR welcome” and then try to make a good guess at what may be feasible for me 🙂#2021-12-1519:49borkdudeSure, you can send PRs for whatever you fancy, regardless of priority#2021-12-1519:50borkdudeThere might also be issues that are not labeled as PR welcome, if you're interested just leave a message#2021-12-1519:52mknoszligi’d gotten the impression that the ones labelled “PR welcome” are relatively easy to start on b/c usually most of the required info is already discussed in the issue#2021-12-1519:52borkdudethat is true#2021-12-1519:53borkdudeit's best to discuss first with other issues to save yourself some work#2021-12-1519:53mknoszligbut i’ll make sure to look around, and also create that test.check issue we talked about in the thread above.. just a bit pressed for time atm#2021-12-1519:54mknoszligyes, that makes sense. and even if nobody starts implementing right away there’s plenty of information if anybody else really wants that feature now and would like to pick it up. i really like the workflow#2021-12-1613:49Jordan RobinsonHey all, on the project I'm currently working on there is both clj-kondo as well as kibit. I was wondering if the linters in clj-kondo are actually a superset of the checks in kibit and if we're getting any benefit from running both, as I'd rather just run clj-kondo Does anyone know if this is the case or can point me in the direction of how to figure it out?#2021-12-1613:50borkdudeI haven't used kibit that much, so I'll defer to the rest of this room#2021-12-1613:55Jordan Robinsonif it helps for context, kibit suggests more idiomatic forms, e.g. if you're testing for (= 0 x) it will recommend (zero? x) (as seen here: https://github.com/jonase/kibit/blob/master/kibit/src/kibit/rules/equality.clj)#2021-12-1614:50wilkerluciohello :) about using Kondo and Meander, how can I tell Kondo to ignore the body from the Meander functions like m/find and m/search? currently I'm doing #_ :clj-kondo/ignore on each form, is there a way to just tell Kondo to ignore the content under these functions?#2021-12-1614:50borkdude@wilkerlucio is this for unresolved symbols?#2021-12-1614:51wilkerlucioyes#2021-12-1614:51borkdudeif so then {:linters {:unresolved-symbol {:exclude [(meander.foo/find)]}}}#2021-12-1614:52borkdudeyou could also write a hook which quotes the question-marked symbols#2021-12-1614:52borkdudeor quotes the entire argument#2021-12-1614:56wilkerlucionice, a cooworker of mine said he may try to tackle this via hooks 🙂#2021-12-1614:57wilkerlucio@borkdude one thing though, now I'm getting errors though warning: Unresolved var: m/app, I tried to do the same with :unresolved-var linter, but they are not going away#2021-12-1614:58borkdudewhat is m/app?#2021-12-1614:59wilkerlucioah, got it now, its a pointer to meander, somehow wasn't finding, but I realize now the exclusion list must be about those names#2021-12-1614:59wilkerluciothis is the config that's working for me:
:unresolved-symbol {:exclude [(meander.epsilon/find)
                                               (meander.epsilon/search)
                                               (meander.epsilon/rewrite)]}
                 :unresolved-var    {:exclude [meander.epsilon/app
                                               meander.epsilon/scan
                                               meander.epsilon/and
                                               meander.epsilon/or
                                               meander.epsilon/pred]}
#2021-12-1615:02wilkerluciothose are defined using defsyntax macro, which looks like a fn, but for some reason when I tried now to meander.epsilon/defsyntax clojure.core/defn, it doesn't fix the issue#2021-12-1615:03wilkerlucioand now we are zero days without having a caching issue 😅#2021-12-1615:06borkdudeyou need to re-lint your deps with this config#2021-12-1615:03wilkerlucioand now we are zero days without having a caching issue 😅#2021-12-1621:43borkdudeclj-kondo 2021.12.16 A pretty big release with several new linters, options and improvements! New • Automatically load configurations from `.clj-kondo///config.edn`. This can be disabled with `:auto-load-configs false`. https://github.com/clj-kondo/clj-kondo/issues/1492 • Add linter `:duplicate-case-test-constant`: detect duplicate case test constants. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#duplicate-case-test-constanthttps://github.com/clj-kondo/clj-kondo/issues/587 (https://github.com/mknoszlig) • Add linter `:unexpected-recur`: warn on `recur` in unexpected (non-tail) position. https://github.com/clj-kondo/clj-kondo/issues/1126 • Add linter `:used-underscored-binding`: warn on used bindings that start with underscore. Disabled by default. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#used-underscored-bindingshttps://github.com/clj-kondo/clj-kondo/issues/1149 (https://github.com/mknoszlig) • Add linter `:docstring-blank` for checking empty docstring. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#docstring-blankhttps://github.com/clj-kondo/clj-kondo/issues/805 (https://github.com/joodie) • Add linter `:docstring-leading-trailing-whitespace` for checking leading and trailing whitespace in docstring. Disabled by default. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#docstring-leading-trailing-whitespacehttps://github.com/clj-kondo/clj-kondo/issues/805 (https://github.com/joodie) • Add linter `:docstring-no-summary` for checking the absence of summary of args in docstring. Disabled by default. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#docstring-no-summaryhttps://github.com/clj-kondo/clj-kondo/issues/805 (https://github.com/joodie) • Add `:exclude-defmulti-args` option for `:unused-bindings` linter. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.mdhttps://github.com/clj-kondo/clj-kondo/issues/1188 (https://github.com/mknoszlig) • Support `:config-in-comment` https://github.com/clj-kondo/clj-kondo/issues/1473. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#override-config-in-comment-forms. Enhanced • Bump built-in cache for clojure 1.11.0-alpha3 and `clojure.data.json` • Reword `:refer` suggestion so you can copy paste it https://github.com/clj-kondo/clj-kondo/issues/1293 (https://github.com/vemv) • Add re-frame analysis output https://github.com/clj-kondo/clj-kondo/issues/1465 (https://github.com/benedekfazekas) • Qualified map causes too many arguments in type checker https://github.com/clj-kondo/clj-kondo/issues/1474 • Handle reader conditional with unknown language https://github.com/clj-kondo/clj-kondo/issues/970
#2021-12-1707:51mknoszligi upgraded to the new version but had a little surprise when looking at a defmulti in a cljc file. :exclude-defmulti-args doesn’t seem to get picked up there:
> echo "(defmulti my-multi (fn [a b] b))" | clj-kondo --lang clj --lint -
linting took 12ms, errors: 0, warnings: 0

> echo "(defmulti my-multi (fn [a b] b))" | clj-kondo --lang cljc --lint -
<stdin>:1:25: warning: unused binding a
linting took 14ms, errors: 0, warnings: 1
is this just a configuration issue on my side?
#2021-12-1707:56borkdudeI suspect the predicate for CLJS isn't right. Try it with a CLJS file#2021-12-1707:57borkdudeI mean the defmulti? pred #2021-12-1708:00mknoszligwith --lang cljs i get the same warning#2021-12-1708:01borkdudeYeah so that's the issue. PR welcome 🙏 #2021-12-1708:01mknoszligi’ll file an issue#2021-12-1709:16n2oHi, thanks for the big release, but there seems to be a problem with re-frames subscriptions. I built a minimal example for this:
(require '[re-frame.core :as rf])

(defn- show-id [subscription]
  (let [id @(rf/subscribe subscription)]
    [:h4 id]))

(defn- ids []
  [show-id [:user/id]])

(rf/reg-sub
 :user/id
 (fn [db _]
   (get-in db [:user :id])))
So there is the component ids, which should show in this example some ids, doesn’t really matter. The subscription key [:user/id] is provided via an argument. But clj-kondo says there is an unused binding: src/main/schnaq/interface/user.cljs:56:17: warning: unused binding subscription
#2021-12-1709:17n2oThe error message points to line 3, where subscription is the parameter of the component.#2021-12-1709:26n2oI filed an issue for this: https://github.com/clj-kondo/clj-kondo/issues/1504#2021-12-1709:30borkdudeThanks for the issue, I'll take a look. /cc @U0508JT9N#2021-12-1709:34benedekhm… the problem could be that we don’t analyze the paramaters of the rf/subscribe apart from the special code which tries to figure out the subs id. so ‘ordinary’ clj-kondo misses the usage of the subscription local#2021-12-1709:35borkdudeyeah, I'm taking a look now#2021-12-1709:37borkdude@U0508JT9N This looks suspicious:
[subscription-id & subscription-params] (:children (first (next (:children expr))))
first next?
#2021-12-1709:38benedeknext gives you a coll and we want the first element, right?#2021-12-1709:38benedektbh we expect that first element to be a vector#2021-12-1709:39benedekwhich not true here apparently#2021-12-1709:39borkdudewhen I change this to
[subscription-id & subscription-params] (next (:children expr))
then it works again
#2021-12-1709:40borkdudeah gotcha, yes, we expected a vector here#2021-12-1709:40borkdude@U1PCFQUR3 perhaps as a workaround you can use that syntax for now?#2021-12-1709:40benedeki don’t think we handle the case when the subs param vector is passed in as a local as in the above bugreport repro example#2021-12-1709:41borkdudeoh right facepalm#2021-12-1709:41borkdudeI'll make a "vector" special case then#2021-12-1709:41benedekthanks#2021-12-1709:43n2oOk, so I’ll just wait for the special case? 🙂 Thanks#2021-12-1709:46borkdudeif you don't want to wait for the fix, I think it might be better if you passed the args to build the subscription instead of the subscription itself, so clj-kondo can see the keyword and static analysis improves by that as well, if in the future you want to find all references#2021-12-1709:48n2oOk sounds reasonable :thumbsup: thanks for your work#2021-12-1709:48borkdude
(defn show-id2 [x y z]
  (let [id @(rf/subscribe [:foobar x y z])]
    [:h4 id]))
#2021-12-1709:49borkdudebut since it's already a subscription, I don't think you need to pass it through subscribe at all#2021-12-1709:49borkdudeyou can directly deref it?#2021-12-1709:49borkdudeor do you pass the vector argument as subscription?#2021-12-1709:50n2oWe’ll pass the vector argument into the subscription#2021-12-1709:51borkduderight#2021-12-1709:56n2oSubscriptions can have arguments, which is why we pass the vector to respect the arguments. Sometimes the subscription key changes, but the provided data follows the same structure, which is why we provide the complete vector for re-frames subscription function#2021-12-1709:57n2oSo we can re-use the components more easily.#2021-12-1710:02borkdudeFixed on master#2021-12-1710:04n2oAwesome 🥳#2021-12-1710:13borkdude@U1PCFQUR3 Not sure if this is blocking anything, I'll wait for some more bug reports related to the new release and then will do a small release soon-ish#2021-12-1710:14n2oWe are fine with this, thanks!#2021-12-1710:21borkdudeyou can use a temporary #_:clj-kondo/ignore on top of the problematic form#2021-12-1709:22Marc O'Morain@borkdude today is an ironic day – I have been repsonsible for accidentally breaking 1000s of peoples builds on CircleCI over the years, but today you broke my build 😄 clj-kondo is warning that our definition of random-uuid is shadowing clojure.core/random-uuid , and we have warnings treated as errors.#2021-12-1709:23Marc O'MorainAlso, thank you for the new version of kondo and all the word you do on it!#2021-12-1709:27borkdude:-D#2021-12-1709:30Marc O'MorainWe have a leiningen project that uses Clojure 1.10, and when we run clj-kondo it’s outputting this:
[clj-kondo] Auto-loading config path: babashka/sci
[clj-kondo] Auto-loading config path: babashka/fs
src/workflows_conductor/entities/uuid.clj:7:1: warning: random-uuid already refers to #'clojure.core/random-uuid
linting took 2223ms, errors: 0, warnings: 1
#2021-12-1709:31borkdudeIs that not desired?#2021-12-1709:31Marc O'Morainour script to invoke it is:
#!/bin/bash -eo pipefail
# Turn off errexit as we want to continue and catch the error code ourselves
set +e

lein clj-kondo --lint src
ret_code_src=$?

echo

# For tests we allow private-call; otherwise use the same config as src
lein clj-kondo --config '{:linters {:private-call {:level :off}}}' --lint test
ret_code_test=$?

# Now fail the job if *either* of the src or test
# invocations returned a non-zero error code
[ "$ret_code_src" -eq 0 -a "$ret_code_test" -eq 0 ]
#2021-12-1709:31Marc O'Morainrandom-uuid isn’t in clojure.core 1.10 right?#2021-12-1709:35Marc O'MorainWe’re going to add (:refer-clojure :exclude [random-uuid]) to our namespace#2021-12-1709:36borkdudeit's in 1.11 and clj-kondo is updated for clojure 1.11 already :)#2021-12-1709:36borkdudebut if you lint your dependencies, clj-kondo will automatically pick up 1.10 again#2021-12-1709:36Marc O'Morainaha, that’s it!#2021-12-1709:36Marc O'MorainThanks!#2022-02-2500:23jvtrigueros@U0K592YDP sorry to raise this thread, but I’m seeing this behaviour as well and am not sure what is meant by “lint your dependencies”, could you share how you got around this?#2022-02-2513:08Marc O'MorainWe worked around this like this by adding the following:
;; With clojure 1.11 alpha, the (random-uuid) function is introduced.
;; We don't have this yet, so let's silence the warning.
;; We may want to consider replacing our custom function with the built-in
;; one if we upgrade clojure.
#_{:clj-kondo/ignore [:redefined-var]}
(defn random-uuid
  "Returns a random type 4 universally unique identifier."
  []
  (UUID/randomUUID))
#2022-02-2513:09borkdudea different solution: (:refer-clojure :exclude [random-uuid])#2022-02-2621:25jvtriguerosThanks!#2021-12-1709:31robert-stuttafordapologies, my google-fu is failing me. how do i clj-kondo on an M1 Silicon mac?#2021-12-1709:31n2oI installed it using homebrew.#2021-12-1709:31robert-stuttafordon an M1 mac?
➜  bootstrap git:(master) ✗ brew install borkdude/brew/clj-kondo
Error: Cannot install in Homebrew on ARM processor in Intel default prefix (/usr/local)!
#2021-12-1709:32borkdudePerhaps this helps? https://apple.stackexchange.com/questions/408375/zsh-bad-cpu-type-in-executable/408379#408379#2021-12-1709:32n2oYes, but you have the same error as I had. If homebrew wants to install in /usr/local, homebrew is trying to install x64 programs.#2021-12-1709:33n2oIf configured correctly, homebrew installs arm-tools in /opt/homebrew.#2021-12-1709:34n2oI had it misconfigured when I switched to an M1 mac, deinstalled it completely, installed it again and then it chose to install arm tools instead. Had it misconfigured, because I migrated via a time machine image from an x64 mac to an arm mac#2021-12-1709:34robert-stuttaford
softwareupdate --install-rosetta
arch -x86_64 brew install borkdude/brew/clj-kondo
#2021-12-1709:34robert-stuttafordthis worked, thank you!#2021-12-1709:35n2oyes but now you have to add the prefix every time. Homebrew can directly prefer arm tools instead.#2021-12-1709:35borkdudeMaybe this should be added to the docs?#2021-12-1709:36n2oActually I am not quite sure if this is really a good solution. In my opinion, you should install the arm-version of homebrew, which then automatically selects the arm-based tools instead.#2021-12-1709:37robert-stuttafordthanks n2o, still in the first hours with the new machine 😅 you've given me enough to dig with, thanks!#2021-12-1709:38n2oI struggled several hours with it, because I do not want to specify the architecture on every installation 😅 A re-installation fixed it in the end. So that homebrew now prefers arm recipes over x64.#2021-12-1709:47robert-stuttafordif you like, @borkdude: https://github.com/clj-kondo/clj-kondo/pull/1505#2021-12-1710:35mknoszligTIL: when running lein test on the clj-kondo repo the user-level (`~/.config..` ) config is applied. depending on the settings, this will cause tests that assume default behaviour to fail. what do you guys do to avoid this?#2021-12-1710:37borkdude@maximilian you can try to add a metadata value on :config-paths ^:replace [] in the default test config, this will make it ignore the home dir#2021-12-1710:37borkdudenot sure if this will make other tests fail :)#2021-12-1712:01mknoszligwell, it does make the test fail that’s supposed to check whether the config in $HOME gets picked up, but that’s a good thing i guess 🙂#2021-12-1712:02mknoszligi’m wondering … what’s your setup for running tests locally without having to comment your personal settings?#2021-12-1712:04borkdudeI guess I don't have conflicting settings with the tests#2021-12-1712:04borkdudeThis is my personal config:
{:linters {:unsorted-required-namespaces {:level :warning}
           :used-underscored-binding {:level :warning}
           #_#_:shadowed-var {:level :off #_warning
                          :include [name]
                          :suggest {name nom}}}}
#2021-12-1712:05borkdudeI'm fine with making the above change and tweaking the default config for the home test#2021-12-1712:06borkdudewhat would be an example of a conflicting config though?#2021-12-1712:08borkdudeas in: can you give me one so I can experience this problem myself?#2021-12-1712:13mknoszligminimal example:
{:linters {:unused-binding {:exclude-destructured-keys-in-fn-args true
                            :exclude-defmulti-args true
                            }}}
#2021-12-1712:13mknoszligfails on lein test :only clj-kondo.bindings-test/unused-binding-test#2021-12-1712:14borkdudeok, but then we can just add the reverse config in the default config for the tests?#2021-12-1712:14mknoszligeither that or in the test cases#2021-12-1712:14borkdudeI'd say in the default config#2021-12-1712:14borkdudeand then override that again in specific tests#2021-12-1712:14mknoszligyeah, that’s better, you’re right#2021-12-1712:17mknoszligone thing we’re doing with this approach however is duplicating default config into the test defaults.#2021-12-1712:21borkdudethere is one default config in test-utils#2021-12-1712:21borkdudethat's the only place where it should be updated I think#2021-12-1712:33mknoszligok… glad to do a PR on this, but it would make sense to set defaults for all existing options, right? the tests that failed now were just due to my specific configuration …#2021-12-1712:34borkdudeOk yes, I'm fine with doing this incrementally too. Whatever makes your life easier#2021-12-1712:37borkdudePerhaps explicitly merging over the default kondo config will work#2021-12-1712:41mknoszligwill try#2021-12-1710:49seriogaI'm trying the new :docstring-no-summary linter. Why is the following positive?
(defn from-string
  "Initialize UUID from string representation.
   Accept only zero-padded representation."
  [_])
dev\clj_kondo_docstring.clj:4:3: warning: First line of the docstring should be a capitalized sentence ending with punctuation.
#2021-12-1710:50borkdude@joost-diepenmaat ^ ?#2021-12-1710:52seriogalooks like it does not work for multiline docstrings...#2021-12-1710:52borkdudeah gotcha#2021-12-1710:53borkdudeI'll make a fix#2021-12-1710:53seriogaShould I file an issue?#2021-12-1710:53borkdudeplease do#2021-12-1710:57borkdudeI also found another issue, I messed up one keyword#2021-12-1710:57borkdudeso if you enable :docstring-no-summary you have also enabled :docstring-leading-trailing-whitespace now ;)#2021-12-1711:03seriogaall these linters look like options for the :missing-docstring :thinking_face:#2021-12-1711:04borkdudedon't understand#2021-12-1711:05seriogasorry, my bad again 😊 forget it#2021-12-1711:56serioga@borkdude how can I test clj-kondo from master? Usually I just install it by scoop.#2021-12-1711:57borkdude@serioga same as here, but update the SHA: https://clojurians.slack.com/archives/CHY97NXE2/p1639585068083000#2021-12-1711:58borkdudeyou can also wait for the build to finish and download the windows binary from appveyor#2021-12-1714:39joost-diepenmaat@serioga I think I messed up the regex for that docstring linter.#2021-12-1714:41mknoszligany test.check users out there? please take a look at https://github.com/clj-kondo/config/issues/16 - if you have linting needs beyond what is already in the ticket feel free to leave a comment 🙂 edit: updated link#2021-12-1714:42borkdude@maximilian Are you aware that you can write hooks for any library / custom macros?#2021-12-1714:45mknoszligyes, but how would they be shared? the standard way would be with the library, correct?#2021-12-1714:46borkdudeYes, and if the lib isn't accepting the contribution then via https://github.com/clj-kondo/config#2021-12-1714:46borkdudeI want to figure out how you can include external configs as dependencies so you will still get them via the same mechanism#2021-12-1714:47borkdudewithout getting them all from the config library, just the ones you need#2021-12-1714:47borkdudeso perhaps we can make up something around that too#2021-12-1714:52mknoszligthat would be great of course#2021-12-1714:53borkdudeWe have done something similar for https://github.com/clj-easy/graal-config But there we hacked this by using :deps/root so we can put everything in one repository#2021-12-1714:53borkdudeBut perhaps we should just make libraries under the clj-kondo organization that we can deploy to clojars, so leiningen users will get them as well#2021-12-1714:54borkdudeso each library would contain just the config and you can include that library in your deps#2021-12-1714:57borkdudeio.github.clj-kondo/config-clojure.test.check {:mvn/version "1.0.0"}#2021-12-1714:59mknoszlighmm… how would that work if you use eg the homebrew version?#2021-12-1715:00borkdudeyes, you would add this to your deps.edn / project.clj and then lint your project as you would always do. clojure-lsp does this automatically#2021-12-1715:00mknoszligah, of course %)#2021-12-1715:07borkdude@maximilian I guess we can just host these libs in one repository so we can use the same :deps/root trick as with graal configs and have an additional project.clj / build.clj in there for mvn deploys#2021-12-1715:07borkdudethat'll probably just mean reorganizing the clj-kondo/config project a bit#2021-12-1715:08mknoszligok, so my issue should move there i guess 🙂#2021-12-1715:10borkdudeyeah, I'd rather see a user-space thing first, eventually we can move it as a built-in but I'd rather not take on more libraries in clj-kondo as built-ins unless they are part of clojure/clojure#2021-12-1715:14mknoszligmakes sense. seeing compojure in impl/analyzer/ gave me the wrong idea i guess 🙂 - but that’s probably been there since before there was clj-kondo/config#2021-12-1715:15borkdudeyes, that's been there from the early days, just like the Schema stuff#2021-12-1715:15borkdudewe can eventually move "popular" configs back into kondo, but it's more flexible to have them outside first since they can be updated separately#2021-12-1916:20borkdudeSmall follow up bug fix release, but even with two new linters by @maximilian! https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#20211219 clj-kondo #2021-12-2011:53fabraoHow do you use clj-kondo in ci process? Before testing or after? How do you invalidate the ci from any kondo condition?#2021-12-2012:15mknoszlighere are some pointers you may find useful: https://github.com/clj-kondo/clj-kondo/blob/master/doc/ci-integration.md#2021-12-2012:46borkdudeThere are various options. Some people configure their CI to fail if clj-kondo fails, other people just use it as a monitoring thing#2021-12-2013:11seriogaHm, the idea behind :docstring-no-summary does not work for docstrings like
"Puts a diagnostic context value `v` as identified with the key `k`
   into the current thread's diagnostic context map.
   Returns a Closeable object who can remove key when close is called.
   The `k` cannot be null.
   If the `v` is null then nothing is put and noop Closeable returned."
I see that clojure.core also has many cases where summary sentence spans multiple lines...
#2021-12-2013:18borkdude@serioga makes sense. I'm open to receive improvements either from you, @joost-diepenmaat or anyone else.#2021-12-2013:25seriogaI guess it's a question to @joost-diepenmaat about concept of this linter 🙂 I like an idea in general but current implementation is not really useful for my codebase.#2021-12-2013:29joost-diepenmaatI’m not surprised this linter triggers many warnings on “good” codebases. It’s pretty hard to summarize a function in a single short line. Personally I really like the style since it forces clarity and it’s part of the clojure style guide but it’s definitely not for everyone. Which is the reason the linter is off by default. #2021-12-2013:30borkdude@joost-diepenmaat I think the issue is that not all sentences are on a first line because of how docstrings are formatted.#2021-12-2013:30borkdude
"Puts a diagnostic context value `v` as identified with the key `k`
   into the current thread's diagnostic context map.
#2021-12-2013:30joost-diepenmaatThe problem is that the line is too long. #2021-12-2013:32joost-diepenmaatAt least that’s my interpretation. I would go with max -80 characters for a summary #2021-12-2013:33joost-diepenmaatIt’s intended that summaries fit on a single line on screen. #2021-12-2013:33borkdudeThat's not really in line with how most clojure code looks and how emacs formats things. I guess this linter is pretty useless for most people if we keep it like this.#2021-12-2013:33seriogaFor me the reference how to write docstrings is clojure.core. But most docstrings in clojure core will not pass this linter 🙂#2021-12-2013:33joost-diepenmaatWe can take a look at what cider does with apropos. That lists the first sentence (not line)#2021-12-2013:36joost-diepenmaatWould still recommend a short first sentence but fine by me to lift te restriction on newlines. #2021-12-2013:37joost-diepenmaatI’m offline for a bit. Will be back later #2021-12-2013:38borkdudeI guess it depends on the idea of "summary". The docstring posted by @serioga doesn't really have a summary, by the definition of the linter (currently).#2021-12-2013:40borkdudebut I guess the idea was inspired by https://guide.clojure.style/#docstring-summary#2021-12-2013:40borkdudeso we should probably implement what is referred to in the style guide by @bozhidar#2021-12-2013:40borkdudewhich is kind of ambigious#2021-12-2013:41borkdudeor not, I don't know.#2021-12-2013:41borkdudeI'll leave it up to you to decide#2021-12-2013:41seriogaWell, for me I see a useful linter that docstring starts from uppercase letter and ends with period, ignoring newlines.#2021-12-2013:42borkdudethe styleguide recommends placing the summary on a single line it seems. The next sentence should not begin on the same line for example.#2021-12-2013:43seriogamakes sense#2021-12-2013:44borkdudeok, let's leave it like this then - sorry to bother you @joost-diepenmaat - a link to the style guide in linters.md would be good#2021-12-2015:34bozhidar@borkdude The idea is simple - each docstring should start with a one-line sentence. This minimizes the work tools have to do to extract some meaningful summary of what a var does (and as a bonus - it plays great with the Emacs minibuffer, that happens to have a height of 1 line).#2021-12-2312:10borkdudeUpdated the docs: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#docstring-no-summary @serioga @joost-diepenmaat#2021-12-2015:35borkdudeok, this is the conclusive info we needed. we just need to update linters.md with it then#2021-12-2015:35bozhidarEven more importantly - it's nice for humans to start with a short and clear summary and then expand on it if needed.#2021-12-2015:36borkdudethanks!#2021-12-2015:36bozhidarYou're welcome!#2021-12-2209:05ingesolHi! Would it make sense with a linter for orgs that want to wrap all fns in a threading form with parentheses? So this:
(-> x
    fn-a
    (fn-b arg1 arg2))
should be corrected to this:
(-> x
    (fn-a)
    (fn-b arg1 arg2))
#2021-12-2209:44borkdudeCan you explain why?#2021-12-2209:47ingesolMy org simply prefers a consistency there, aesthetically I guess.#2021-12-2209:48ingesolWe all have our special ways 🙂#2021-12-2209:48borkdudeYou can write a hook for it I think#2021-12-2209:49ingesolI thought hooks were for parsing, will have a look#2021-12-2209:56borkdude@U21QNFC5C you can use them for linting too. I got it working here: .clj-kondo/thread_hook.clj
(ns thread-hook
  (:require [clj-kondo.hooks-api :as api]))

(defn thread-hook [{:keys [node]}]
  (let [children (rest (:children node))]
    (run! (fn [node]
            (when-not (api/list-node? node)
              (api/reg-finding! (assoc (meta node)
                                       :message (str "Wrap in a list: " node)
                                       :type :org.acme/thread-list)))) children)))
#2021-12-2209:56borkdude.clj-kondo/config.edn
{:hooks {:analyze-call {clojure.core/-> thread-hook/thread-hook}}
 :linters {:org.acme/thread-list {:level :warning}}}
#2021-12-2209:56borkdude
$ cat example.clj
(-> 1 2 3)
#2021-12-2209:56borkdude
$ clj-kondo --lint example.clj
example.clj:1:5: warning: Wrap in a list: 1
example.clj:1:7: warning: Wrap in a list: 2
example.clj:1:7: error: a number is not a function
example.clj:1:9: warning: Wrap in a list: 3
example.clj:1:9: error: a number is not a function
linting took 74ms, errors: 2, warnings: 3
#2021-12-2210:16ingesolyou are too fast, I did not have time to have a look 🙂#2021-12-2210:16ingesolthanks for this, will try it out#2021-12-2214:39alekszelarkI wonder why it complains about parse-long? clojure-lsp version used: 2021.12.20-00.36.56 clj-kondo version used: 2021.12.19#2021-12-2214:40borkdude@zelark parse-long is a new var in clojure 1.11 and clj-kondo has already been updated for that#2021-12-2214:40borkdudehowever if you lint your deps, then it should pick up on your project's clojure version I think#2021-12-2214:47alekszelarkHm, I linted via cli and it doesn’t complain about parse-long , maybe it’s a Calva specific issue, or I don’t know#2021-12-2214:48alekszelark> if you lint your deps what does it mean? I have
{:paths ["src" "resources"]
 :deps {org.clojure/clojure {:mvn/version "1.11.0-alpha3"}
...
#2021-12-2214:52alekszelarkjust figured out that I have clj-kondo extension installed in my vs code, after I deleted it, things look nice again, thanks#2021-12-2214:52borkdudeok cool.#2021-12-2214:55practicalli-johnIs {:paths ["."]} a legitimate configuration for .clj-kondo/config.edn ? Background: I am using https://github.com/github/super-linter for markdown and it should do Clojure as well, but suspect its not finding the deps.edn file in the root of the project (practicalli/clojure-deps-edn). I think I just need to put in the config what I would otherwise specify on the command line with the --lint flag. Does that make sense?#2021-12-2215:00borkdude@jr0cket clj-kondo config.edn doesn't know anything about :paths#2021-12-2215:03practicalli-johnHmm, I'll take a look at the Super Linter PRs that added clj-kondo and see if I can work out why its not picking up the deps.edn file. I have a separate GitHub action that specificially checks the deps.edn file, using the lint deps.edn` command line arg, so not a big issue. Nice to have just one GitHub action though 🙂#2021-12-2215:04borkdudeclj-kondo doesn't pick up on deps.edn automatically#2021-12-2215:05borkdudeclj-kondo --lint $(clojure -Spath) --dependencies + clj-kondo --lint src:test is usually how you should lint your projects#2021-12-2215:09practicalli-johnIn DeLaGuardo/setup-clj-kondo github action I use the following, which seems to work. This isnt for a Clojure project, its for a user level config project, so it only has a deps.edn file plus some markdown for docs, nothing else Clojure wise.
jobs:
  lint:
    runs-on: ubuntu-20.04
    steps:
      - uses: DeLaGuardo/
#2021-12-2215:09borkduderight, yes, you are linting the deps.edn file itself, that should work#2021-12-2215:10practicalli-johnI'll see if I can get Super Linter to do the same. But if not, its still covered. Thanks.#2021-12-2215:28practicalli-johnSuper Linter is calling clj-kondo with the following command, so not sure what path would be used by default.
clj-kondo --config ${CLOJURE_LINTER_RULES} --lint
Would it be better to specify "." as the argument to --lint (assuming neither clojure or lein commands are available in the GitHub action image). Or do specific directories need to be added for src and test, etc.?
#2021-12-2215:30borkdudeI have no idea how Super Linter works. I don't think specifying . is always a good default.#2021-12-2215:30borkdudeI'd say just use clj-kondo directly#2021-12-2215:32borkdudeunless you can find good examples of how other people use it. https://grep.app is a tool you can maybe use for this#2021-12-2215:33practicalli-johnSuper Linter just runs the command above (and uses the latest clj-kondo it seems) I wonder if I do a PR to add a CLOJURE_LINTER_PATHS variable to the super linter then the paths can be specified in the github action yaml file that defined the jobs (maybe).#2021-12-2215:34borkduderunning --lint without any arguments doesn't do anything, so I would be surprised if that was all there is to it. Are you supposed to provide arguments to it yourself?#2021-12-2215:36practicalli-johnAs --lint without arguments doesnt do anything, that would explain my results. Thanks. I'll try figure out how to add some paths to the command. 🙂#2021-12-2216:05practicalli-johnThere are some options to set paths, but they arent being passed to the Clojure linter. It seems https://megalinter.github.io/latest/descriptors/clojure_clj_kondo/what I think super-linter should do for clj-kondo, so I'll switch to that. Thanks.#2021-12-2216:06borkdudeOh I didn't even realize those were different things#2021-12-2216:08practicalli-johnLooking at the config options, they are very different: I'd consider super-linter broken for now until there is an env var to set the lint path (a PR adding the setup of mega-linter to super linter seems to be required - but then why not just use mega-linter 🙂 )#2021-12-2216:09practicalli-johnMega linter has some very nice docs for clj-kondo https://megalinter.github.io/latest/descriptors/clojure_clj_kondo/#2021-12-2216:10borkdudecool! :)#2021-12-2308:06orestisGood morning. I'm wondering what's the best way to make clj-kondo work with macro-generated defs that come from static resources. Concrete example: we have a directory full of SVG icons, and each icon file gets turned into a var via a macro. Obviously when connected via the REPL, this works as expected and you also get completions. But clj-kondo rightfully complains as those vars don't appear in the source.#2021-12-2308:07orestisThe custom macroexpansion is an obvious place to try, but then it's mostly duplicating the code plus you'd need access to the classpath to locate the directory which contains the files.#2021-12-2308:13borkdudeIn this case I would generate a stub file using clj-easy stub or manually#2021-12-2308:13borkdudeOr just add this namespace to the excludes in the unresolved var linter#2021-12-2308:18orestisIs this relevant? https://clojure-lsp.io/settings/#stub-generation#2021-12-2308:18borkdudeYes#2021-12-2308:30orestisOh that wouldn't work for cljs, hm.#2021-12-2308:32borkdudeYeah, but you can apply a similar trick. Emit the list of files to a clj file in your kondo dir and then use that in the hook#2021-12-2308:34orestisHm, I'd like to avoid the manual sync step. Because in the end I could just evaluate the macro and paste the results back in the original file.#2021-12-2308:36borkdudeThat will be the most robust solution and will work for both kondo and cursive #2021-12-2308:57orestisBTW, The stub doesn't work, because the two namespaces are named the same (e.g. foo/icons.clj , foo/icons.cljs). The vars now live inside the foo/icons.clj while they're used from foo/icons.cljs. It seems like clj-kondo correctly looks at the CLJS file but other parts of the tooling is not.#2021-12-2309:01orestisHm, putting the literal defs (via eval/replace) into the clj file actually works, but I think it shouldn't?#2021-12-2309:14borkdudewhy shouldn't it?#2021-12-2309:18orestisThe CLJS compiler isn't happy about that. If you have two namespaces with the same name, only macros make it automatically across, from CLJ->CLJS. So if from say nosco/login.cljs you require nosco.icons and you use nosco.icons/check , the check var has to be placed in nosco/icons.cljs, not nosco/icons.clj#2021-12-2309:19orestisWhereas clj-kondo doesn't complain about undeclared vars no matter where the var is.#2021-12-2309:19borkdudethen why don't you emit this to a .cljs file?#2021-12-2309:20orestisOh I did now, just flagging this as something that surprised me on behalf of clj-kondo's behaviour. Interestingly, if I do the exact same via a stub it doesn't seem to work.#2021-12-2309:20orestisI will probably need to start with a clean project and troubleshoot.#2021-12-2309:20borkdudecool yeah, clj-kondo might be a little bit erring on the side of false negatives here#2021-12-2309:21orestis👍#2021-12-2311:23wilkerlucioone very simple solution is to use declare, in case the icons don't keep varying much it's easy to automate, and makes it work with every tool, example: https://github.com/fulcrologic/fulcro/blob/develop/src/main/com/fulcrologic/fulcro/dom.cljs#L17-L30#2021-12-2311:23borkdude:thumbsup:#2021-12-2317:31practicalli-johnMegaLinter works great for my deps.edn file, although it uses an older version of clj-kondo and throwing a few errors about very new configs. I'm trying to encourage the https://github.com/megalinter/megalinter/pull/1119 I've also created a https://github.com/megalinter/megalinter/pull/1126#2021-12-2317:31borkdudeThanks!#2022-12-2618:44scaturrHow does one handle dependencies via :macroexpand? I use camel-snake-kebab to generate a name and when I run clj-kondo I get an error like this:
WARNING: file camel_snake_kebab/core.clj not found while loading hook
WARNING: error while trying to read hook for my.lib/defmagic: Could not find namespace: camel-snake-kebab.core.
#2022-12-2618:58borkdudeyou cannot load dependencies from hooks unless you put those dependencies in your config dir. but I don't recommend doing that, keep your hooks as small as possible for better performance#2022-12-2618:59scaturrAh. Thank you 🙂#2022-12-2621:44Kurt HarrigerHi there, I wanted to contribute a few documentation updates to the fulcro user guide https://github.com/fulcrologic/fulcro-developer-guide/pull/98/files which currently includes a step
[#clj-kondo]*clj-kondo support*: Fulcro exports configs for the clj-kondo linter (used e.g. by Calva). To import them, create `.clj-kondo/config.edn` containing `{}` and run `clj-kondo --copy-configs --dependencies --lint (clojure -Spath)` and follow the printed instructions for adding them to the config file.
When I ran this it appeared to do nothing. I think this step is obsolete as vscode did not complain about defsc and as far as I can tell clj-kondo can now discover these configs automatically… but I was asked if I could confirm before they merge these documentation changes.
#2022-12-2710:08wilkerluciohello, I saw it but, altough its not required to include de config paths, running with —copy-configs is still required to happen once#2022-12-2621:47borkdudeYes, the newest clj-kondo now does this automatically :thumbsup:#2022-12-2701:14wilkerluciothe part of copying the configs from the deps is also automatic now? (no need for --copy-configs?)#2022-12-2707:50borkdudeThat part still requires the flag #2022-12-2819:12Kurt Harrigerso if I rm -r .clj-kondo and rm -r .lsp an then restart visual studio I can confirm that vscode is automatically downloading config files into .clj-kondo folder evne without an empty config.edn file.
tree -a .clj-kondo -L 1
.clj-kondo
├── .cache
├── com.fulcrologic
└── com.wsscode
This appears to happen when starting up clojure lsp. If I delete the .clj-kondo folder without removing the .lsp folder the files do not reappear. If I then run clj-kondo --copy-configs --dependencies --lint '(clojure -Spath)' and check the .clj-kondo folder it does create a .cache/lock file but it does not seem to otherwise download any files until clojure lsp is started
#2022-12-2819:13borkdude
--lint '$(clojure -Spath)'
#2022-12-2819:13borkdudeyou forgot the dolllar#2022-12-2819:15Kurt Harrigeroh interesting the fulcro dev guide did not have this $ either and command listed there gave an error#2022-12-2819:15Kurt HarrigerI thought it needed to be quoted, but actually it needed a $#2022-12-2819:16Kurt Harrigereither way it doesn’t seem this command is necessary as they do seem to automaticallly be downloaded when clojure lsp starts#2022-12-2819:16Kurt Harrigeris it worth putting this back in the development guide with the $ ? are there cases where it is necessary to do this manually#2022-12-2819:28borkdudenot everyone uses clojure-lsp#2022-12-2819:29borkdudebut you can add a note that if you do, then it executes those commands already#2022-12-2819:43Kurt Harriger:thumbsup: thanks#2022-12-2710:33practicalli-johnMegalinter updated to clj-kondo 2021-12-19 now https://github.com/megalinter/megalinter/pull/1126#2022-12-2715:09thumbnailNot sure if carve -related questions go here too; Running carve 0.1.0 in one of my projects runs into a NPE
❯ carve --opts '{:paths ["src" "test"]}'
Exception in thread "main" java.lang.NullPointerException
        at clojure.core$namespace.invokeStatic(core.clj:1605)
        at clojure.core$namespace.invoke(core.clj:1599)
        at carve.impl$ignore_QMARK_.invokeStatic(impl.clj:183)
        at carve.impl$ignore_QMARK_.invoke(impl.clj:176)
        at carve.impl$do_run_BANG_$fn__18981.invoke(impl.clj:260)
        at clojure.core$complement$fn__5687.invoke(core.clj:1443)
        at clojure.core$filter$fn__5912.invoke(core.clj:2825)
        [...]
But i'm not sure where to start looking, any pointers?
#2022-12-2715:22borkdude@jeroen.dejong can you try again with df552797a198b6701fb2d92390fce7c59205ea77?#2022-12-2715:22thumbnailWill do!#2022-12-2715:31thumbnailIt's working again. Not sure why, but thanks 🙂#2022-12-2715:31borkdudeI'm not sure either, if you can post the code which was problematic, then I could reproduce, but it's fixed now#2022-12-2715:32thumbnailI'm running it in a rather big (private) project; so i'm not sure why it happened. I'm sure I broke something while refactoring; which borked the loading#2022-12-2800:00fabraohello all, Why is this happening?
(ns some-ns
    (:require [com.wsscode.pathom3.plugin :as p.plugin]
              [com.wsscode.pathom3.connect.indexes :as pci]))

(let [one-registers spec-plugin (p.plugin/register (plugins/spec-check-attributes spec-plugin-react-fn))
        institutions-resolvers (pci/register [resolvers ...])])
p.plugin/register -> Unresolved var
pci/register -> Unresolved var
#2022-12-2801:22seancorfield@fabrao You seem to have five items in that let binding -- it should be an even number.#2022-12-2802:01fabrao@seancorfield it´s warning clj-kondo information, maybe it´s configuring :lint-as {com.fulcrologic.guardrails.core/>def    clojure.spec.alpha/def} as I see in pathom config.edn .clj-kondo#2022-12-2802:01fabraothe warning gone#2022-12-2802:02seancorfieldRegardless, the code you posted is invalid syntax -- a copy'n'paste error @fabrao?#2022-12-2802:05fabraowell, it´s not complete code, I was wonder only for warning message explain, so I looked at source of pathom to discover what kind of pci/register is to handle it in clj-kondo#2022-12-2903:19Chad kennedyI have a line of code (let [path (.getPath ^object app "userData")] where clj-konda says Unresolved symbol: object. I believe, and correct me if I'm wrong, that object here is the javascript class named object. (The source file is a .cljs file) How can I get clj-kondo to understand that?#2022-12-2903:29Chad kennedyCode context, if needed: https://github.com/logseq/logseq/blob/59fde1b41fd91bc84b8c1040823182ef627b4b18/src/electron/electron/handler.cljs#L252#2022-12-2903:35seancorfieldShouldn't that be ^Object?#2022-12-2903:43Chad kennedyI really don't know. I'm new to the codebase, and hoping to help by starting small and doing a little linting. 😕 I'm not sure what else object would be in this case. It's not shown in the require at the top of the file.#2022-12-2903:47Chad kennedyNow, this object usage is only occurring in .cljs files within the src/electron/electron folder of the codebase. Maybe object is an electron thing?#2022-12-2903:48seancorfieldYeah, just looking over that code I suspect you're right but clj-kondo doesn't know how to find it...?#2022-12-2903:49Chad kennedyThat's correct. I'm getting Unresolved symbol: object#2022-12-2903:52Chad kennedyInteresting. Here, line 72 clj-kondo resolves object fine, or at least doesn't flag an error. But it does flag an error on line 76: https://github.com/logseq/logseq/blob/master/src/electron/electron/search.cljs#L72#2022-12-2903:53Chad kennedy(Same error: Unresolved symbol: object)#2022-12-2904:05Chad kennedySeeing it work on line 72 here, but not line 76, makes me think it might be a bug in clj-kondo, regardless of what object is in this case. But I am pretty new at all this, so I might be misunderstanding the syntax.#2022-12-2904:20Chad kennedyI confirmed I can replace object with my name on line 72, and I won't get an error#2022-12-2904:25seancorfieldSo that indicates clj-kondo is just ignoring the context of the type hint in line 72...#2022-12-2908:08borkdudeIssue welcome #2022-12-2913:47Yehonathan Sharvit@borkdude What do you think of adding a clj-kondo warning for unsafe usage of read-string (that could be exploited to execute arbitrary code)?#2022-12-2913:49borkdudeThere is an issue for more general linter for this where you can configure read-string: https://github.com/clj-kondo/clj-kondo/issues/996 Feel free to upvote the issue with a thumbs up#2022-12-2922:30borkdudeCursive users take note! @brcosta has been doing amazing work on integrating clj-kondo with Cursive. See these screenshots! You can try out this plugin by going to preferences > plugins > install from disk https://www.dropbox.com/s/uo6fiquyowa6qe0/clj-stuff-plugin-0.3.0.zip?dl=0 It will likely be renamed to a better name and available in the marketplace within a few days.#2022-12-2923:36kennyCool. What's the difference from the previous clj-kondo integration? Looks like an IntelliJ plugin. Is the source code available online?#2022-12-2923:37borkdude@U083D6HK9 The source code is here: https://github.com/brcosta/clj-stuff-plugin The difference is that this is likely more performant, and less work to set up, but I'll defer to @brcosta for better info on this.#2022-01-0312:10brcostaHey guys! Yes, zero-conf, more performant and now we can make clj-kondo more tightly integrated with Intellij 🙂#2022-12-3015:05MatthewLisp👋 Hello everyone We want to use Kondo in your Github Actions, I'm taking a look at https://github.com/DeLaGuardo/clojure-lint-action However what I'm trying to figure out is, does kondo finding a problem will block my merge? I want something more flexible like being able to see the problems found as annotations, but if i want to merge, it won't stop me from doing so I know this have nothing to do directly with Kondo, but maybe someone already did something more flexibile on GH Actions#2022-12-3015:06borkdudeDon't know if that is configurable. I would expect so. Perhaps Github Actions supports this regardless of the action. Let's ask @delaguardo#2022-12-3015:11borkdude@matthewlisp It seems you can use continue-on-error #2022-12-3015:16MatthewLispThank you very much @borkdude I think this will do 😄#2022-12-3015:45fabrao@borkdude I tried with continue-on-error but, some how it's failling. Or we understand in wrong way?#2022-12-3015:46borkdudeSome checks were not successful, but you can still merge, isn't this what you want?#2022-12-3015:51fabraoWell yes, but I think the way I want to work is change the way of CI work, that change the icon act like warn icon not error icon#2022-12-3015:54borkdudeI'm not sure how this should be done. Perhaps @U7ERLH6JX or @delaguardo know.#2022-12-3015:54borkdudeLet's continue in this thread.#2022-12-3015:58delaguardoBased on how i remember GH API there's no warn status for jobs. Only success or failure#2022-12-3016:00delaguardoMaybe they change it recently but i can't check it right now#2022-12-3016:02lispycloudstheres this status or conclusion called neutral which probably is the closest to what you want i guess but theres no good way to set it it seems. see: • https://github.com/actions/toolkit/issues/146https://github.community/t/github-actions-neutral-exit-code-is-incorrectly-interpreted-as-failure/16088https://github.com/actions/runner/issues/662 exit code 78 was supposed to set it and even the REST api documents it but not sure if it can be used.#2022-12-3016:05lispycloudsmaybe it could be done via an api call to https://docs.github.com/en/rest/reference/checks#update-a-check-run but it would be quite cumbersome, @delaguardo would probably know better 😄#2022-12-3016:06borkdudeAn alternative would be to set all linter levels to :info in your clj-kondo config ;)#2022-12-3016:06borkdudeor :warning #2022-12-3016:08borkdudeThere is also a --fail-level setting for clj-kondo, but I don't know if that works with @delaguardo’s plugin#2022-12-3016:15lispycloudsLooks like we can set it via the js sdk: https://github.com/wearerequired/lint-action/blob/master/src/index.js#L128 probably we need it as a feature in the clojure-lint-action. cc @delaguardo#2022-12-3016:16lispycloudshttps://github.com/wearerequired/lint-action/pull/192#2022-01-0113:45pinkfrogclj-kondo complains the missing of the site ns as in here: https://github.com/juxt/site/blob/master/src/juxt/site/alpha/triggers.clj/#L10. How can I teach it to understand?#2022-01-0113:47borkdudeAre you allowed to use Clojure 1.11? Then you can use as-alias which kondo already understands #2022-01-0113:55pinkfrogI can, thanks for the info!
#2022-01-0114:36pinkfrogWhat’s the ‘as-alias’ you are referring to? Searching https://clojure.github.io/clojure/branch-master/index.html has no result.#2022-01-0114:39borkdudeThat info is here: https://clojure.org/news/2021/09/17/deref#2022-01-0114:40borkdudeIt's a new option in :require#2022-01-0114:50pinkfrogYes. It’s there: https://clojure.github.io/clojure/branch-master/clojure.core-api.html#:~:text=the%20current%20namespace.%0A%3A-,as%2Dalias%20takes%20a,-symbol%20as%20its#2022-01-0114:52borkdude
(ns foo (:require [foobar :as-alias foo]))
::foo/bar ;; :foobar/bar 
#2022-01-0114:51borkdudeA happy new year!#2022-01-0313:44brcosta#2022-01-0313:51borkdude@UQTHDKJ8J Feel free to make a PR to the editor integration page of clj-kondo's docs#2022-01-0314:42pinkfrogHow to tell cljkondo to stop complain about the unresolved symbols on this line: https://github.com/juxt/site/blob/master/bin/site/#L1179. ? These symbosl are actually created by some macros in the ansi package#2022-01-0314:43borkdude@i You can find configs on this page for every linter: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-var Also you can configure :lint-as to handle the macro which defines the colors.#2022-01-0315:33pinkfrogThe colors are generated by this line: https://github.com/AvisoNovate/pretty/blob/master/src/io/aviso/ansi.clj#L72#2022-01-0315:33pinkfrogAnd access in this way: https://github.com/juxt/site/blob/master/bin/site/#L1179#2022-01-0315:34pinkfrogIn this case, what’s the proper way to hide the unresolved warnings?#2022-01-0315:34borkdudeI already told you#2022-01-0315:35borkdudeUse the config from the README I linked to :)#2022-01-0315:39pinkfrogThe :list-as approach is not applicable here. and (declare some-ns/name) is also invalid.#2022-01-0315:39borkdudeI mean this one: > You can find configs on this page for every linter: > https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-var#2022-01-0315:39borkdudeYou can add an :exclude [the-full-namespace] for that linter#2022-01-0315:41pinkfrogThanks for that.#2022-01-0413:48pinkfrogBy the way, is it possible to exclude the namespace by directly specifying in that file instead of in the config.edn?#2022-01-0413:49borkdudeyou can specify the config in your namespace's metadata#2022-01-0416:44borkdudeclj-kondo + clojure-extras intellij plugin docs: https://github.com/clj-kondo/clj-kondo/blob/master/doc/editor-integration.md#clojure-extras-plugin thank you @brcosta#2022-01-0419:31borkdudeFYI: I'm offering enterprise support/consulting for those that need an extra level of support around my projects (or related work). https://blog.michielborkent.nl/oss-highlights-nov-dec-2021.html#enterprise-support Recurring sponsors get a discount on the hourly rate.#2022-01-0516:09imreWe bumped into an interesting issue with clj-kondo hooks vs tools.namespace/refresh. A one-liner repro case is:
clj -Srepro -Sdeps '{:deps {org.clojure/tools.namespace {:mvn/version "1.2.0"} seancorfield/next.jdbc {:git/url "" :git/sha "24bf1dbaa441d62461f980e9f880df5013f295dd"}}}' -M -e "((requiring-resolve 'clojure.tools.namespace.repl/refresh-all))"
#2022-01-0516:09imreresult:
:reloading (next.jdbc.protocols next.jdbc.prepare next.jdbc.result-set next.jdbc.datafy next.jdbc.types next.jdbc.transaction next.jdbc.default-options next.jdbc.connection next.jdbc.sql.builder next.jdbc.sql-logging next.jdbc next.jdbc.sql next.jdbc.specs hooks.com.github.seancorfield.next-jdbc next.jdbc.quoted next.jdbc.date-time next.jdbc.optional next.jdbc.plan)
:error-while-loading hooks.com.github.seancorfield.next-jdbc
#error {
 :cause "Could not locate hooks/com/github/seancorfield/next_jdbc__init.class, hooks/com/github/seancorfield/next_jdbc.clj or hooks/com/github/seancorfield/next_jdbc.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name."
 :via
 [{:type java.io.FileNotFoundException
   :message "Could not locate hooks/com/github/seancorfield/next_jdbc__init.class, hooks/com/github/seancorfield/next_jdbc.clj or hooks/com/github/seancorfield/next_jdbc.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name."
   :at [clojure.lang.RT load "RT.java" 462]}]
 :trace
 [[clojure.lang.RT load "RT.java" 462]
  [clojure.lang.RT load "RT.java" 424]
  [clojure.core$load$fn__6856 invoke "core.clj" 6115]
  [clojure.core$load invokeStatic "core.clj" 6114]
  [clojure.core$load doInvoke "core.clj" 6098]
  [clojure.lang.RestFn invoke "RestFn.java" 408]
  [clojure.core$load_one invokeStatic "core.clj" 5897]
  [clojure.core$load_one invoke "core.clj" 5892]
  [clojure.core$load_lib$fn__6796 invoke "core.clj" 5937]
  [clojure.core$load_lib invokeStatic "core.clj" 5936]
  [clojure.core$load_lib doInvoke "core.clj" 5917]
  [clojure.lang.RestFn applyTo "RestFn.java" 142]
  [clojure.core$apply invokeStatic "core.clj" 669]
  [clojure.core$load_libs invokeStatic "core.clj" 5974]
  [clojure.core$load_libs doInvoke "core.clj" 5958]
  [clojure.lang.RestFn applyTo "RestFn.java" 137]
  [clojure.core$apply invokeStatic "core.clj" 669]
  [clojure.core$require invokeStatic "core.clj" 5996]
  [clojure.core$require doInvoke "core.clj" 5996]
  [clojure.lang.RestFn invoke "RestFn.java" 421]
  [clojure.tools.namespace.reload$track_reload_one invokeStatic "reload.clj" 35]
  [clojure.tools.namespace.reload$track_reload_one invoke "reload.clj" 21]
  [clojure.tools.namespace.reload$track_reload invokeStatic "reload.clj" 52]
  [clojure.tools.namespace.reload$track_reload invoke "reload.clj" 43]
  [clojure.lang.AFn applyToHelper "AFn.java" 154]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.lang.Var alterRoot "Var.java" 308]
  [clojure.core$alter_var_root invokeStatic "core.clj" 5499]
  [clojure.core$alter_var_root doInvoke "core.clj" 5494]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.tools.namespace.repl$do_refresh invokeStatic "repl.clj" 94]
  [clojure.tools.namespace.repl$do_refresh invoke "repl.clj" 83]
  [clojure.tools.namespace.repl$refresh_all invokeStatic "repl.clj" 162]
  [clojure.tools.namespace.repl$refresh_all doInvoke "repl.clj" 147]
  [clojure.lang.RestFn invoke "RestFn.java" 397]
  [clojure.lang.Var invoke "Var.java" 380]
  [user$eval1 invokeStatic "NO_SOURCE_FILE" 1]
  [user$eval1 invoke "NO_SOURCE_FILE" 1]
  [clojure.lang.Compiler eval "Compiler.java" 7181]
  [clojure.lang.Compiler eval "Compiler.java" 7136]
  [clojure.core$eval invokeStatic "core.clj" 3202]
  [clojure.main$eval_opt invokeStatic "main.clj" 488]
  [clojure.main$eval_opt invoke "main.clj" 482]
  [clojure.main$initialize invokeStatic "main.clj" 508]
  [clojure.main$null_opt invokeStatic "main.clj" 542]
  [clojure.main$null_opt invoke "main.clj" 539]
  [clojure.main$main invokeStatic "main.clj" 664]
  [clojure.main$main doInvoke "main.clj" 616]
  [clojure.lang.RestFn applyTo "RestFn.java" 137]
  [clojure.lang.Var applyTo "Var.java" 705]
  [clojure.main main "main.java" 40]]}
#2022-01-0516:11borkdudeWhere does clj-kondo come in into the above?#2022-01-0516:11imrethis is caused by a combination of: • referring a lib by git coordinates, which means that it will appear as a directory on the classpath • said lib exporting clj-kondo hooks • clj-kondo hooks themselves being .clj files • those files normally having a namespace inside them that does not appear in code proper (and this is totally fine)#2022-01-0516:12imrecause "Could not locate hooks/com/github/seancorfield/next_jdbc__init.class#2022-01-0516:13imreI ended up writing a somewhat hacky helper function which tries to exclude clj-kondo.exports directories from the default refresh-dirs of tools.namespace:
(defn remove-clj-kondo-exports-from-tools-ns-refresh-dirs
  "Opinionated helper that addresses the problem that happens when:

  - a lib is referenced via a git dependency
  - said lib exports clj-kondo hooks (which are clojure source files)
  - and the namespace in those files is not something that also exists in a proper source file
    (this is normally not the case at the time of writing this, see
     for example)
  - and clojure.tools.namespace.repl/refresh(-all) is used

  Call this in your user.clj to (hopefully) fix the problem.

  A potential issue from using this is that if the directory containing the clj-kondo.exports folder
  also directly contains to-be-reloaded clojure source files, those will no longer be reloaded."
  []
  (->> (clojure.java.classpath/classpath-directories)
       (mapcat
        (fn [^File classpath-directory]
          (let [children   (.listFiles classpath-directory)
                directory? #(.isDirectory ^File %)
                clj-kondo-exports?
                           #(= "clj-kondo.exports" (.getName ^File %))
                has-clj-kondo-exports
                           (some (every-pred clj-kondo-exports? directory?) children)]
            (if has-clj-kondo-exports
              (->> children
                   (filter directory?)
                   (remove clj-kondo-exports?))
              [classpath-directory]))))
       (apply clojure.tools.namespace.repl/set-refresh-dirs)))
#2022-01-0516:14imreand then (remove-clj-kondo-exports-from-tools-ns-refresh-dirs) in user.clj#2022-01-0516:14borkdudeThere was a similar issue recently with better-cond and cursive where cursive mistook exported hooks as application code#2022-01-0516:14borkdudeI'm not sure what the right answer here is. I would say it's a tooling problem#2022-01-0516:14imreYes, I've bumped into that too#2022-01-0516:16borkdudeWe could support some extension .cljk or so to prevent other things from loading it... but then highlighting etc won't work as nicely. Tooling should probably have ways to exclude things from loading#2022-01-0516:16imreCertainly a tooling problem. Whether the tool is clj-kondo or tools.namespace here, I'm not sure 🙂#2022-01-0516:17imreYeah, either a custom ext or nicer exclusion mechanisms for tools.namespace would help#2022-01-0516:18imreI would actually vote for the latter, given hooks are already out there and you'd have to support the current .clj extensions#2022-01-0516:18borkdudeindeed#2022-01-0516:20imreSince there isn't a tools.namespace channel here, I guess I'll refer to ask.clojure#2022-01-0518:03imrehttps://ask.clojure.org/index.php/11434/could-namespace-refresh-sophisticated-directory-filtering#2022-01-0522:56imreSo @U064X3EF3 commented on this raising the question of why are these files under the lib's (next.jdbc's) path? What are the location requirements for clj-kondo hooks?#2022-01-0522:57borkdudeThe requirements are that these files are on the classpath under a clj-kondo.exports directory so clj-kondo knows what to copy to the local config directory#2022-01-0522:58borkdudeIt encounters these files while linting dependencies#2022-01-0522:58borkdudeif they are not on the classpath, clj-kondo will never see them#2022-01-0523:04imreDrat.#2022-01-0523:05imreI'm not sure how to resolve this, then.#2022-05-0909:03imreso Alex recently commented on this again on ask.clojure, it appears a non-clj extension would be the "officially supported" solution: https://ask.clojure.org/index.php/11434/could-namespace-refresh-sophisticated-directory-filtering?show=11882#c11882#2022-05-0909:08borkdude@U08BJGV6E I think there might be another workaround#2022-05-0909:08imreinterested#2022-05-0909:08borkdudeWe could make a clj-kondo hooks "shim" library so the namespaces are defined, but they don't do actually anything#2022-05-0909:09borkdudeyou could do this in your own project to start#2022-05-0909:09borkdudeJust define:
(ns clj-kondo.hooks-api)
yourself
#2022-05-0909:09borkdudeif you are sure that you're not using clj-kondo as a dependency in your project#2022-05-0909:10borkdudealthough I think having a filter in that reloading library would be a better solution#2022-05-0909:10borkdudea different extension would give different problems I'm sure#2022-05-0909:11imreFor now I think I'd prefer my current workaround I detailed above tbh. While the tools.ns filter would be welcome, Alex seems to be on the position that distributing .clj files with a lib means you're distributing those namespaces#2022-05-0909:12imreAnd as such if you give an instruction to load all namespaces from the lib, clojure isn't at fault for trying to load them#2022-05-0909:12borkdudeWhat if we supported .cljk ? But then we'd have to be sure there would be not other language in the future adopting that extension :/#2022-05-0909:12imreHis suggestion was to just use .edn#2022-05-0909:13borkdudeThat's not correct in the case of clj-kondo hooks. Did you explain this was used for clj-kondo hooks?#2022-05-0909:13imreYep#2022-05-0909:14borkdudeAnyway, perhaps you can PR your current workaround as documentation for clj-kondo hooks? At least we've got something#2022-05-0909:14imreIt's all in the question on ask.#2022-05-0909:14imreI can for sure.#2022-05-0909:15borkdudeA link to the ask issue is also fine#2022-05-0909:15imreWhy would .edn be a problem for clj-kondo?#2022-05-0909:15borkdudeit would be a problem for tooling, an .edn file cannot contain language constructs that .clj can#2022-05-0909:15borkdudeso clj-kondo itself would already vomit warnings all over your hooks code#2022-05-0909:16borkdudeor at least, not right now, but probably in the future when we would include such warnings#2022-05-0909:16imrewhat about a file extension that is based off edn and not clj? Like ednk or something along those lines? Or even .clj-kondo or .hook#2022-05-0909:16borkdudee.g. #(foo %) and @foo are not supported in .edn#2022-05-0909:16imreSomething that doesn't imply "clojure source" to Clojure itself#2022-05-0909:17borkdude
foo/bar/hook.kondo
#2022-05-0909:17imreI have to agree with Alex on hooks themselves being only data from the library consumer's point of view#2022-05-0909:17imreAnd since clj source files imply code to Clojure, perhaps this data shouldn't be in clj files#2022-05-0909:18borkdudeThey are Clojure files executed by clj-kondo#2022-05-0909:18borkdudeso I don't agree. A library could also bundle scripts that it would execute using load-file in some special context#2022-05-0909:20imreWould you mind commenting on the question there, then? I don't think I have enough weight in the community to have an effect on this either way#2022-05-0909:21imreI'd dig a .kondo extension, that would be very specific#2022-05-0909:21borkdudeLet's support the .kondo extension, or maybe even .clj_kondo or .clj-kondo?#2022-05-0909:23borkdudeif we will support another extension, the other uphill battle would be to convince other hook authors to use that extension#2022-05-0909:23borkdudeso I think you would still need your workaround#2022-05-0909:24borkdudelinking to the ask issue + workaround in the docs seems like the best overall solution#2022-05-0909:24borkdudeWe could also support .cljc#2022-05-0909:24imreWhere in the docs you think this would be best placed?#2022-05-0909:25borkdudeand then you could use a reader conditional for clj-kondo ;)#2022-05-0909:25borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2022-05-0909:26borkdudeProbably this section: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#tips-and-tricks#2022-05-0909:26imreI think one of the problems here is that these files are not on the classpath where clojure would look for them if it tried to require one of these namespaces#2022-05-0909:26borkdudeisn't the problem that they are on the classpath?#2022-05-0909:26borkdudeand that it tries to load a namespace that doesn't exist in the JVM classpath#2022-05-0909:27borkdudee.g.:
(ns my-hooks #?(:clj-kondo (:require [clj-kondo.hooks-api])))
#2022-05-0909:27borkdudebut that seems like a terrible workaround as well#2022-05-0909:27imre
; clj -Srepro -Sdeps '{:deps {org.clojure/tools.namespace {:mvn/version "1.2.0"} seancorfield/next.jdbc {:git/url "" :git/sha "24bf1dbaa441d62461f980e9f880df5013f295dd"}}}' -M -e "((requiring-resolve 'clojure.tools.namespace.repl/refresh-all))"

:reloading (next.jdbc.protocols next.jdbc.prepare next.jdbc.result-set next.jdbc.datafy next.jdbc.types next.jdbc.transaction next.jdbc.default-options next.jdbc.connection next.jdbc.sql.builder next.jdbc.sql-logging next.jdbc next.jdbc.sql next.jdbc.specs hooks.com.github.seancorfield.next-jdbc next.jdbc.quoted next.jdbc.date-time next.jdbc.optional next.jdbc.plan)
:error-while-loading hooks.com.github.seancorfield.next-jdbc
#error {
 :cause "Could not locate hooks/com/github/seancorfield/next_jdbc__init.class, hooks/com/github/seancorfield/next_jdbc.clj or hooks/com/github/seancorfield/next_jdbc.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name."
 :via
 [{:type java.io.FileNotFoundException
   :message "Could not locate hooks/com/github/seancorfield/next_jdbc__init.class, hooks/com/github/seancorfield/next_jdbc.clj or hooks/com/github/seancorfield/next_jdbc.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name."
   :at [clojure.lang.RT load "RT.java" 462]}]
 :trace
 [[clojure.lang.RT load "RT.java" 462]
  [clojure.lang.RT load "RT.java" 424]
  [clojure.core$load$fn__6908 invoke "core.clj" 6161]
  [clojure.core$load invokeStatic "core.clj" 6160]
  [clojure.core$load doInvoke "core.clj" 6144]
  [clojure.lang.RestFn invoke "RestFn.java" 408]
  [clojure.core$load_one invokeStatic "core.clj" 5933]
  [clojure.core$load_one invoke "core.clj" 5928]
  [clojure.core$load_lib$fn__6850 invoke "core.clj" 5975]
  [clojure.core$load_lib invokeStatic "core.clj" 5974]
  [clojure.core$load_lib doInvoke "core.clj" 5953]
  [clojure.lang.RestFn applyTo "RestFn.java" 142]
  [clojure.core$apply invokeStatic "core.clj" 669]
  [clojure.core$load_libs invokeStatic "core.clj" 6016]
  [clojure.core$load_libs doInvoke "core.clj" 6000]
  [clojure.lang.RestFn applyTo "RestFn.java" 137]
  [clojure.core$apply invokeStatic "core.clj" 669]
  [clojure.core$require invokeStatic "core.clj" 6038]
  [clojure.core$require doInvoke "core.clj" 6038]
  [clojure.lang.RestFn invoke "RestFn.java" 421]
  [clojure.tools.namespace.reload$track_reload_one invokeStatic "reload.clj" 35]
  [clojure.tools.namespace.reload$track_reload_one invoke "reload.clj" 21]
  [clojure.tools.namespace.reload$track_reload invokeStatic "reload.clj" 52]
  [clojure.tools.namespace.reload$track_reload invoke "reload.clj" 43]
  [clojure.lang.AFn applyToHelper "AFn.java" 154]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.lang.Var alterRoot "Var.java" 308]
  [clojure.core$alter_var_root invokeStatic "core.clj" 5535]
  [clojure.core$alter_var_root doInvoke "core.clj" 5530]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.tools.namespace.repl$do_refresh invokeStatic "repl.clj" 94]
  [clojure.tools.namespace.repl$do_refresh invoke "repl.clj" 83]
  [clojure.tools.namespace.repl$refresh_all invokeStatic "repl.clj" 162]
  [clojure.tools.namespace.repl$refresh_all doInvoke "repl.clj" 147]
  [clojure.lang.RestFn invoke "RestFn.java" 397]
  [clojure.lang.Var invoke "Var.java" 380]
  [user$eval1 invokeStatic "NO_SOURCE_FILE" 1]
  [user$eval1 invoke "NO_SOURCE_FILE" 1]
  [clojure.lang.Compiler eval "Compiler.java" 7194]
  [clojure.lang.Compiler eval "Compiler.java" 7149]
  [clojure.core$eval invokeStatic "core.clj" 3215]
  [clojure.main$eval_opt invokeStatic "main.clj" 488]
  [clojure.main$eval_opt invoke "main.clj" 482]
  [clojure.main$initialize invokeStatic "main.clj" 508]
  [clojure.main$null_opt invokeStatic "main.clj" 542]
  [clojure.main$null_opt invoke "main.clj" 539]
  [clojure.main$main invokeStatic "main.clj" 664]
  [clojure.main$main doInvoke "main.clj" 616]
  [clojure.lang.RestFn applyTo "RestFn.java" 137]
  [clojure.lang.Var applyTo "Var.java" 705]
  [clojure.main main "main.java" 40]]}
#2022-05-0909:28imre
"Could not locate hooks/com/github/seancorfield/next_jdbc__init.class, hooks/com/github/seancorfield/next_jdbc.clj or hooks/com/github/seancorfield/next_jdbc.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name."
#2022-05-0909:28borkduderight#2022-05-0909:28imrecause they are under .....exports somewhere#2022-05-0909:28borkdudethen why does it load this file at all#2022-05-0909:28imrebut my issue is that Clojure even attempts to load them#2022-05-0909:29borkdudeit's the same issue with a test runner, it loads a file to scan for tests. every sane test runner has a config option to skip certain namespaces / directories#2022-05-0909:29borkdudeto prevent loading#2022-05-0909:30imreAfair tools.ns looks for clojure source files on directory paths, then parses out the namespace name from their ns forms, then tries to load those namespaces#2022-05-0909:30borkdudeyes. it should have the option, is my opinion, but I'm not going to spend any time trying to convince the core team#2022-05-0909:31borkdudeI'll leave it at this for now: • document your workaround • if more related issues come up, we can consider the extension#2022-05-0909:31imreWould you like me to record an issue for the latter?#2022-05-0909:32borkdudeOne related issue in the past has been that Cursive also analyzes hook code and when you have same-named hooks then you end up navigating to the wrong file#2022-05-0909:32borkdudeyes please#2022-05-0909:32imreYep, I also had that in Cursive#2022-05-0909:32borkdudeThe solution in Cursive was to just use a different ns for the hook code, but the extension would also save the day here I guess#2022-05-0909:33imreIf there's an issue about it, I can also link to that#2022-05-0909:33imreNeed to head out now, will do these in the afternoon#2022-05-0909:33borkdudethe issue is in the better-cond repo#2022-05-0909:33imreThank you for your time#2022-05-0909:36imreOh actually, one more reason for the custom extension: tools.build compilation: https://clojurians.slack.com/archives/C02B5GHQWP4/p1651685386479149#2022-05-0909:36imreI ran into that just last week#2022-05-0909:36borkdude:thumbsup:#2022-05-0909:37borkdudeok, the argument is getting more compelling now#2022-05-0913:11imrehttps://github.com/clj-kondo/clj-kondo/pull/1684 for the docs#2022-05-0913:21borkdudeThanks, merged :)#2022-05-0913:30imreThank you#2022-05-0913:30imreAnd here's the issue, I tried to collect everything without being too wordy: https://github.com/clj-kondo/clj-kondo/issues/1685#2022-01-0615:14borkdudeClj-kondo Sublime Text integration docs: https://github.com/clj-kondo/clj-kondo/blob/master/doc/editor-integration.md#sublime-text#2022-01-0621:15ghadilinter idea: (update x :foo #(bar % a b)) -> (update x :foo bar a b)#2022-01-0621:16dpsuttonsounds tough to discern the good case from (update x :foo #(bar a % b)) but i like that idea#2022-01-0621:17dpsuttonor maybe i’m inventing complexity and its not that hard#2022-01-0621:18ghadiprobalby not hard for borkdude 🙂#2022-01-0621:18ghadiI guess any such function (like swap!) where the update fn uses its argument in the second position of its singular form#2022-01-0621:18borkdudeThis is probably doable. Up till 3 args this seems ok, but more than that it's going to use apply which in some cases would affect performance somewhat? Depends on hot path of course#2022-01-0621:18ghadi(swap! atom (fn [x] (something x anything)))#2022-01-0621:19borkdudeoh wait#2022-01-0621:19borkdudeit's always a single arg function in the first case#2022-01-0621:19borkdudeor is it#2022-01-0621:20ghadithe function will be arity (+ 1 (count trailing-args-to-swap))#2022-01-0621:20ghadibut the 99% common case is that beginners don't know about the update function taking multiple args#2022-01-0621:21ghadithat case: (update-in m [:foo] #(inc %))#2022-01-0621:21ghadirather than (update-in m [:foo] inc)#2022-01-0621:22ghadiin fact a more generic lint would be if someone passes a function #(inc %) rather than inc#2022-01-0621:22ghadianywhere (like map), not just update-in#2022-01-0621:23ghadiI didn't try that, maybe it's already linted#2022-01-0621:23dpsuttonI’m trying to think of corner cases where it might be difficult to realize you can’t use this
(update x :foo #(bar a (merge % {:a :b}) b))
(update x :foo #(bar a (let [x %] (inc x)) b))
(update x :foo #(bar a (inc %) b))
(update x :foo #(bar a % %))
#2022-01-0621:24ghadithose are all fine#2022-01-0621:26ghadithe rule would be: "anonymous arity-1 function of a single expression passed to swap/update, where the singular arg appears only in the second position in the form"#2022-01-0621:28ghadibut I think I'd be ok with a more general rule#2022-01-0621:28borkdudethe hardest part would be a name for the linter#2022-01-0621:28ghadianonymous function that just forwards to a var: (fn [x] (foo x)) or #(foo %) rather than foo#2022-01-0621:29ghadiunnecessary-anonymous-fn-expr#2022-01-0621:30ghadithat would catch 99% of the update/swap cases too#2022-01-0621:41borkdudeok, that's a good one to start with.#2022-01-0621:45borkdudeI wrote an issue here: https://github.com/clj-kondo/clj-kondo/issues/1526#2022-01-0710:58borkdude@dharrigan finally found the solution to your issue! https://github.com/clj-kondo/clj-kondo/issues/1468#2022-01-0710:58borkdudeit was a misconfiguration - we should definitely have linting for clj-kondo's own config. made an issue here: https://github.com/clj-kondo/clj-kondo/issues/1527#2022-01-0710:59dharriganw00t!#2022-01-0711:02dharriganDoes this mean that if I move the lint-as outside of linters, it should just work?#2022-01-0711:02borkdudeyes#2022-01-0711:03dharriganfantastic. doing right now#2022-01-0711:03dharriganright, it's at the same level now as :linters#2022-01-0711:04dharriganLooking good!#2022-01-0717:21lreadI think I might be the king of typos. I somehow didn’t notice, for longer than I’ll admit, that I’d typed :false instead of false. Is detecting this kind of foolishness clj-kondo-worthy?#2022-01-0717:22Noah BogartGlad to know I'm not the only one who does this! #2022-01-0717:43lreadsimple_smile Should we form a support group?#2022-01-0813:11Mateusz MazurczakHi, I use clj-kondo with cursive (clojure-extras). Clj-kondo highlights <! function as an error "Unresolved symbol <!".#2022-01-0813:14borkdudeCan you give more context?#2022-01-0813:23Mateusz MazurczakWhole clojure.core.async library functions are highlighted as unresolved#2022-01-0813:24borkdudeok, let me check how they are defined#2022-01-0813:24Mateusz Mazurczakexample: (buffer 5) clj-kondo: Unresolved symbol: buffer#2022-01-0813:25borkdudebut how are you importing them#2022-01-0813:25borkdudeI need a complete reproduction file to be able to reproduce it locally#2022-01-0813:26borkdudeAre you using :refer :all perhaps?#2022-01-0813:30Mateusz MazurczakAh yeah, sorry
(ns app.home2.panel
  (:require [app.state.core :as state]
            [app.state.panel :as panel]
            [app.listennotes.search-input-field :as search-podcast]
            [app.audio.upload :as audio-upload]
            [app.view.util :as utils]
            [app.getting-started.wizard :as wizard]
            [app.util :as u]
            [app.util.string :as util-string]
            [cljs-http.client :as http]
            [clojure.string :as str]
            [app.view.colors :as c]
            [ :as home-help])
  (:require-macros [cljs.core.async.macros :refer [go]]))

(defn find-rss-url
  "If the user has provided a website link instead of a RSS feed URL,
   the server tries to find a link to the RSS feed in the website."
  [url]
  (go
    (let [response (<! (http/request
                         {:request-method :post
                          :url "/podcast-import/find-rss-url"
                          :transit-params {:url url}}))]
          (get-in response
              [:body
               :url]))))
#2022-01-0813:31borkdudeDon't you need to :refer [<!] as well?#2022-01-0813:33borkdudehttps://github.com/clojure/core.async/blob/68d21860625e2080e041d5c09fcae2809610a191/src/main/clojure/cljs/core/async.cljs#L92
(:require [cljs.core.async :refer [<!]])
#2022-01-0813:34borkdudelike here: https://github.com/clojure/core.async/blob/68d21860625e2080e041d5c09fcae2809610a191/src/test/cljs/cljs/core/async/tests.cljs#L13#2022-01-0816:57Mateusz MazurczakCode works without the reference, but this helps with the highlighting error. Thank you very much#2022-01-0817:03borkdudeI have no idea why it works without the refer, but you're supposed to do it like this :)#2022-01-0818:12Mateusz MazurczakOne more thing in cljs, about js/window.location.hash Some functions from js are not higlighted. (js is not required in any way). But the window.location is highlighted as "cannot be resolved"#2022-01-0818:14Mateusz Mazurczakexample: (js/console "smth") <- it's fine (set! js/window.location.hash ..) js/window.location.hash cannot be resolved#2022-01-0818:15borkdude@U0281QDFE1X does it say "clj-kondo" in that message? otherwise it might be coming from Cursive.#2022-01-0818:16borkdudeI don't think clj-kondo has a problem with this:
$ clj-kondo --lint - --lang cljs <<< '(set! js/window.location.hash "foo")'
linting took 15ms, errors: 0, warnings: 0
#2022-01-0818:16Mateusz MazurczakOh right, sorry, it is not clj-kondo#2022-01-0818:16Mateusz MazurczakThank you very much for your help#2022-01-0818:17borkdudeyou can disable the cursive linting separately I think#2022-01-0916:47borkdudehttps://twitter.com/ikitommi/status/1480215765143932931 (cc @brcosta)#2022-01-0918:19ikitommiwhere should I put the malli (library) clj-kondo file so it gets picked up for library users? Have two configs locally, one for the lib and another as the user schemas for the project (generated)
.clj-kondo
  metosin
    malli
      config.edn ;; this one
    malli-types
      config.edn
#2022-01-0918:20ikitommicurrently:
{:lint-as {malli.experimental/defn schema.core/defn}}
 :linters {:unresolved-symbol {:exclude [(malli.core/=>)]}}}
#2022-01-0918:21ikitommicould merge those into the generated file, but if there is a way not to do it, I’m all 👂s.#2022-01-0918:25borkdude@U055NJ5CC do you want to export a configuration?#2022-01-0918:25ikitommihow do I do it?#2022-01-0918:25borkdudeCheck these docs: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration List of examples: https://github.com/clj-kondo/clj-kondo/issues/1383 Let me know if you get stuck.#2022-01-0918:27ikitommithanks!#2022-01-0918:27borkdudetl;r: you have to make a resources/clj-kondo.exports/metosin/malli directory and that directory contains the exported config.edn#2022-01-0918:28borkdudeand you can refer to your own exported config (as a developer of the library) in .clj-kondo/config.edn with :config-paths [".../resources/clj-kondo.exports/metosin/malli"]#2022-01-0918:29borkdudeas a user of the library, clj-kondo will copy the configuration when you lint the classpath with:
clj-kondo --lint $(clojure -Spath) --dependencies --copy-configs
#2022-01-0918:29borkdudethe above is done by clojure-lsp automatically#2022-01-0918:43ikitommithe guide was excellent, did all that. Would be great if Cursive or Clojure Extras would do the auto-import with Idea too.#2022-01-0918:47borkdudeI've discussed with @brcosta and he will probably do that#2022-01-1102:12pfeodrippe[RESOLVED] Hi \o I'm trying to update my clj-kondo from the CLI and I'm having (it appears to be an GH issue, but letting here just FYI). But I'm able to download the zip from the releases page o/
$ ./install-clj-kondo
Downloading 
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "">
<html>
  <head>
    <title>503 Backend.max_conn reached</title>
  </head>
  <body>
    <h1>Error 503 Backend.max_conn reached</h1>
    <p>Backend.max_conn reached</p>
    <h3>Guru Mediation:</h3>
    <p>Details: cache-for8427-FOR 1641867116 4140388333</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>/clj-kondo-
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "">
<html>
  <head>
    <title>503 Backend.max_conn reached</title>
  </head>
  <body>
    <h1>Error 503 Backend.max_conn reached</h1>
    <p>Backend.max_conn reached</p>
    <h3>Guru Mediation:</h3>
    <p>Details: cache-for8427-FOR 1641867116 4140388333</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>-macos-amd64.zip to /tmp
#2022-01-1110:17borkdudeCan't reproduce:
$ mkdir k
$ ./install-clj-kondo --dir k
Downloading  to /tmp
Successfully installed clj-kondo in k
Must be a Github hiccup
#2022-01-1114:24pfeodrippeYes, thanks, I guess it was it, want me to delete the message?#2022-01-1114:25borkdudeIt's fine#2022-01-1114:30pfeodrippeDoes clj-kondo have a way to say that a :type-mismatch function type is closed? For example, instead of
{:arities {1 {:args [{:op :keys,
                      :req {:person-external-id :string}}],
              :ret {:op :keys,
                    :req {:name :string}}}}}
we would have something like
{:arities {1 {:args [{:op :keys,
                      :req {:person-external-id :string}}],
              :ret {:op :keys,
                    :closed true ;; <<--------------
                    :req {:name :string}}}}}
and the return could be used for stronger type inference. I have seen that there is https://github.com/clj-kondo/clj-kondo/issues/783, but it's just weakly related from where I see.
#2022-01-1114:31pfeodrippeI could help on it if needed o/ Just don't know where to start#2022-01-1114:37borkdudeIt hasn't got this. I think we should first discuss if we want this before starting on an implementation. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/dev.md#workflow#2022-01-1114:37borkdudeI think the related issue should be solved first before you would even benefit from this probably, but that you could explain in a Github Discussion or issue#2022-01-1114:39pfeodrippeYes, sure, I wouldn't start a PR without an issue o/ Thanks, so I will wait for the related issue to be resolved and I see what's needed from there (also it will give me more time to understand more of the clj-kondo codebase)#2022-01-1114:39pfeodrippeThanks o/#2022-01-1114:40borkdudeYou could perhaps look into solutions(s) for the open issue. I haven't really investigated this myself yet#2022-01-1114:45pfeodrippeOk, nice, I will try to check it after this weekend (vacation). Is https://github.com/clj-kondo/clj-kondo/blob/d9fca2705863e3e604e004ccb942e0b3d2e268ec/src/clj_kondo/impl/types.clj#L318 a good place to start to look into this issue?#2022-01-1114:47borkdudeyeah#2022-01-1114:48pfeodrippeThanks o/#2022-01-1121:57Mateusz MazurczakClj-kondo marks
(keep #(if (odd? %) %) (range 10))
as missing else branch, where it is okay to do it like this https://clojuredocs.org/clojure.core/keep#example-542692cfc026201cdc326e82 Also the problem I have with it is that the whole editor goes yellow. (screen below)
#2022-01-1121:58borkdude@mateusz.mazurczak.dev It is ok, but the style clj-kondo encourages is to use when if you don't have an else branch.#2022-01-1121:58borkdudeThe yellow thing is something in the plugin, not something clj-kondo can fix. /cc @brcosta#2022-01-1122:00borkdudeYou can post an issue here about the yellow stuff: https://github.com/brcosta/clj-stuff-plugin#2022-01-1122:05Mateusz MazurczakThanks for the response. I will report that. Also the errors stay the same for a long time unless I go and edit it more. So for example as you mentioned I changed if -> when. But the clj kondo still marks it as the previous error missing else branch. This happens often and is really annoying. Here is a recording of the issue: https://watch.screencastify.com/v/d65Ebva8KvLDIdUTJofr#2022-01-1122:58brcostaHi, thanks for reporting! I’m aware of the issues, just need some more time to fix them! Already have a proof of concept for the lag thing. About the missing branch going all yellow it’s the way Intellij highlights warnings, maybe I need to use another type of annotator for these cases, I’ll see. Again, thanks for reporting! 🙂#2022-01-1203:14brcostaI just uploaded a fix for the performance issue, we need to wait for Jetbrains to approve it. If you want to test it sooner just DM me and I can send a prebuilt install package. About the yellow highlight I guess the easiest fix is to edit the default color scheme. If I have any other idea I let you know 😉#2022-01-1122:05borkdudePlease post that in the issue, I can't do anything about this. It's in the plugin.#2022-01-1122:06borkdudeIt's helpful that you have the screencast though, for the plugin author to see what's going on.#2022-01-1122:06borkdudeI also noticed that lag and it's indeed annoying#2022-01-1122:07Mateusz MazurczakYeah, spending minute on the error because you have whole screen yellow is pretty annoying#2022-01-1122:08Mateusz MazurczakEspecially if some warning shows while writing code and stays after you finish#2022-01-1122:08borkdudehttps://github.com/brcosta/clj-stuff-plugin :)#2022-01-1122:08Mateusz MazurczakSorry, just ranting 😄#2022-01-1122:09borkdudeTry emacs until the issue is fixed ;-)#2022-01-1122:28Mateusz MazurczakI recently switched to intelllj from emacs, maybe I will go back 😉#2022-01-1207:28borkdudehttps://clojurians.slack.com/files/UQTHDKJ8J/F02TF25PKCN/clj-extras-plugin-0.4.0.zip#2022-01-1207:28borkdudeCan you try this one? Bruno fixed the lag but not yet the other problem #2022-01-1211:43brcostaGood news, it’s already approved by Jetbrains, you can update directly in IDEA now#2022-01-1212:10borkdudeThe latest clojure-extras plugin for IntelliJ which integrates clj-kondo, has a lot better performance! https://plugins.jetbrains.com/plugin/18108-clojure-extras/ Thank you @brcosta!#2022-01-1212:10borkdudeping @U0281QDFE1X#2022-01-1212:10borkdude@brcosta Perhaps you can also rename the github repo to clojure-extras and also link to the marketplace from there.#2022-01-1212:12borkdudeI think the locations of the yellow stuff can be fixed by the plugin, perhaps. I did a similar thing in clj-kondo.lsp for Calva. https://github.com/clj-kondo/clj-kondo.lsp/blob/53b59828bfc6a6dab8c67ca4e1442093fec4b5c8/server/src/clj_kondo/lsp_server/impl/server.clj#L76-L88#2022-01-1212:57brcostaI’ll try this approach later today 🙂#2022-01-1213:17ericdallocatjam#2022-01-1215:51Noah Bogartin the library semantic-csv, there are a bunch of casting functions (`->int` converts a value to an int if possible), which are defined using an in-house function called clone-var. The block of code that defines them is wrapped in a reader conditional and I’m not sure exactly how to make these functions lint as functions: https://github.com/metasoarous/semantic-csv/blob/10f436bacf2ca9ed2f22ffbbecea6467ba20c2e4/src/semantic_csv/core.cljc#L321-L335#2022-01-1215:52Noah Bogartany ideas how to make clj-kondo recognize or at least stop marking them as “unresolved var”?#2022-01-1216:02borkdude@nbtheduke :lint-as {foo.bar.impl/clone-var clojure.core/declare}#2022-01-1216:04borkdudeehm no, sorry#2022-01-1216:06borkdudeyou can add this namespace to {:linters {:unresolved-var {:exclude [semantic-csv.core]}}} or make a proper macro for it in .clj-kondo#2022-01-1216:07borkdudeThe macro would look something like:
(defmacro clone-var [sym] (def ~(symbol (name sym)) ~sym)))
#2022-01-1216:08borkdudeand then add to :macroexpand {foo.bar.impl/clone-var my_hooks/clone-var}#2022-01-1216:08borkdudeand the code would then live in .clj-kondo/my_hooks.clj or so#2022-01-1216:10Noah Bogartcool, i’ll give that a whirl! thank you for the help#2022-01-1216:20Alex Miller (Clojure team)I have the same problem as https://github.com/clj-kondo/clj-kondo/issues/272, which is closed. any advice? Repro:
git clone 
cd tools.deps.alpha
clj -M:lint

src/main/clojure/clojure/tools/deps/alpha/specs.clj:122:9: error: Unresolved symbol: clojure.tools.deps.alpha/resolve-deps
src/main/clojure/clojure/tools/deps/alpha/specs.clj:126:9: error: Unresolved symbol: clojure.tools.deps.alpha/make-classpath-map
src/main/clojure/clojure/tools/deps/alpha/specs.clj:130:9: error: Unresolved symbol: clojure.tools.deps.alpha/make-classpath
#2022-01-1216:22borkdudeLet me take a look locally. Is this on tda master?#2022-01-1216:23Alex Miller (Clojure team)yep#2022-01-1216:25borkdudeThe error goes away when I add [clojure.tools.deps.alpha] to the namespace form. I think clj-kondo expects the fdef name to be related to one of your loaded namespaces.#2022-01-1216:25borkdude
(ns clojure.tools.deps.alpha.specs
  (:require [clojure.spec.alpha :as s]
            [clojure.tools.deps.alpha]))
#2022-01-1216:25Alex Miller (Clojure team)but that's not necessary#2022-01-1216:25Alex Miller (Clojure team)it's just a symbol going in the registry#2022-01-1216:26borkdudehm yeah, it can be any fully qualified symbol. I'll fix that then#2022-01-1216:28borkdudeThis is the config which makes those things go away for now:
{:skip-args [clojure.core/comment]
 :linters
 {:unused-binding {:level :off}
  :unresolved-symbol [(clojure.spec.alpha/fdef)]}}
#2022-01-1216:28borkdudeyou can also apply this config locally in the namespace#2022-01-1216:28borkdudeor before the form even:
#_:clj-kondo/ignore 
#2022-01-1216:30borkdude:skip-args [clojure.core/comment] can be written as :skip-comments true as well#2022-01-1216:30borkdudeyou can also apply a separate config for comment forms:
:config-in-comment {...}
#2022-01-1216:32borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1532#2022-01-1216:33Alex Miller (Clojure team)when I added that :unresolved-symbol line above, I suddenly got 100s of warnings/errors#2022-01-1216:34Alex Miller (Clojure team)seemed weird that was a vector and not a key in a map?#2022-01-1216:35borkdudeAh sorry, my bad.
{:skip-comments true
 :linters
 {:unused-binding {:level :off}
  :unresolved-symbol {:exclude [(clojure.spec.alpha/fdef)]}}}
#2022-01-1216:35borkdudeI still have to write a linter for clj-kondo's own config file :)#2022-01-1216:36borkdudethe (..) means, within a call to. without the parens it means: ignore this symbol itself globally. I kind of regret this but I stole this 2.5 years ago based on what joker was doing at the time. sorry about that ;)#2022-01-1216:43borkdudeyou can also say: :exclude [(foo.bar/baz [x y z])] which ignores only the symbols x y z within calls to foo.bar/baz#2022-01-1216:43borkdudewhich some macros which introduce arbitrary symbols can use#2022-01-1216:48borkdudeI checked the implementation of the fdef analysis and it was explicitly written as: if the namespace is unresolved, then the symbol is reported as unresolved. Since you can easily make typos and most people will load the namespace when they write specs.#2022-01-1216:51borkdudebut I guess this should be an opt-in warning and not an error#2022-01-1216:51Alex Miller (Clojure team)I tried that config and it didn't suppress the errors#2022-01-1216:52borkdudewhich config did you try?#2022-01-1216:52Alex Miller (Clojure team)your last code block above#2022-01-1216:52borkdudethis one?
{:skip-comments true
 :linters
 {:unused-binding {:level :off}
  :unresolved-symbol {:exclude [(clojure.spec.alpha/fdef)]}}}
#2022-01-1216:52Alex Miller (Clojure team)yes#2022-01-1216:53borkdudeit does work over here. are you sure you have that exact config with #2022-01-1216:53borkdudeI forgot to add that before#2022-01-1216:53Alex Miller (Clojure team)yes#2022-01-1216:54Alex Miller (Clojure team)
% cat .clj-kondo/config.edn
{:skip-comments true
 :linters
 {:unused-binding {:level :off}
  :unresolved-symbol {:exclude [(clojure.spec.alpha/fdef)]}}}
% clj -M:lint
src/main/clojure/clojure/tools/deps/alpha/specs.clj:122:9: error: Unresolved symbol: clojure.tools.deps.alpha/resolve-deps
src/main/clojure/clojure/tools/deps/alpha/specs.clj:126:9: error: Unresolved symbol: clojure.tools.deps.alpha/make-classpath-map
src/main/clojure/clojure/tools/deps/alpha/specs.clj:130:9: error: Unresolved symbol: clojure.tools.deps.alpha/make-classpath
linting took 1088ms, errors: 3, warnings: 0
#2022-01-1216:57borkdudeah my bad again, I get the same. argh, yeah, it uses a "custom" way to handle that so configuring won't work.#2022-01-1216:57borkdude
#_:clj-kondo/ignore ;; see kondo issue #1532
(s/fdef clojure.tools.deps.alpha/resolve-deps
  :args (s/cat :deps ::deps-map :options ::resolve-args)
  :ret ::lib-map)
#2022-01-1216:58borkdudethat will do it, or load the ns, until I fix the issue which I'm on right now.#2022-01-1217:00Alex Miller (Clojure team)thx#2022-01-1218:41borkdude1532 is fixed on master#2022-01-1218:46Alex Miller (Clojure team)thx!#2022-01-1408:39borkdudeFixed in newest kondo and 0.4.5 of the plugin: https://plugins.jetbrains.com/plugin/18108-clojure-extras/#2022-01-1216:21Alex Miller (Clojure team)I tried adding a suppression in the config per that issue, but it did not suppress#2022-01-1218:46ingesolSeeing some strange behaviour using Cursive + clojure extras + clj-kondo. A number of vars are reported as unresolved, while they are clearly not. Only inside cursive, not in clj-kondo CLI#2022-01-1218:47borkdude@brcosta Are you sending the :filename ... so clj-kondo can see that this is .cljs code?#2022-01-1218:47borkdudeThat is likely the issue#2022-01-1218:48ingesolthat would make sense, I think I also saw this on some reagent vars#2022-01-1218:48ingesolreagent is cljs source, IIRC#2022-01-1219:03borkdudecould you make an issue at https://github.com/brcosta/clj-stuff-plugin so we don't forget?#2022-01-1304:48Michael GardnerI'm writing a simple CLI tool that uses clj-kondo's analysis output. Working with clj-kondo has been very pleasant!#2022-01-1304:50Michael GardnerI'm trying to make things fast now, and I noticed that it doesn't seem any faster to run the analysis the second time, even though a cache is created in .clj-kondo . Is this expected? How can I verify what clj-kondo is doing with the cache? I tried setting :debug true but didn't see any extra output at all, so I'm probably holding it wrong#2022-01-1308:01borkdudeThe analysis output itself isn't cached. The cache is used to look up info about other namespaces for linting: it's only used for functionality used by clj-kondo itself. If you want to do this as a user you should implement your own cache.#2022-01-1312:47borkdudeGoing to add some linting for .clj-kondo/config.edn. Any suggestions for common mistakes?#2022-01-1312:49borkdudeThe first one I've added is:#2022-01-1314:17dharriganIt's been pretty good so far, the one that caught me out recently was having a top-level key nested under another top-level key.#2022-01-1314:17dharrigan(as you know 🙂 )#2022-01-1314:19borkdudeyes, I have a lint for that now :). see thread: https://clojurians.slack.com/archives/CHY97NXE2/p1642078177088700?thread_ts=1642078060.088600&amp;cid=CHY97NXE2#2022-01-1315:04borkdudeclj-kondo 2022.01.13: a linter for Clojure code that sparks joy clj-kondo • Add linter `:conflicting-fn-arity`: warn when an arity occurs more than once in a function that overloads on arity. https://github.com/clj-kondo/clj-kondo/issues/1136 (https://github.com/mknoszlig) • Add linter `:clj-kondo-config` which provides linting for `.clj-kondo/config.edn`. https://github.com/clj-kondo/clj-kondo/issues/1527 • Relax `:reduce-without-init` for functions known to be safe https://github.com/clj-kondo/clj-kondo/issues/1519 • Symbol arg to `fdef` can be arbitrary namespace https://github.com/clj-kondo/clj-kondo/issues/1532 • Improve potemkin generated var-definition analysis https://github.com/clj-kondo/clj-kondo/issues/1521 (https://github.com/ericdallo) • Stabilize cache version independent from kondo version https://github.com/clj-kondo/clj-kondo/issues/1520. This allows you to re-use the cache over multiple kondo versions. • :output {:progress true} should print to stderr https://github.com/clj-kondo/clj-kondo/issues/1523 • Only print informative messages when `--debug` is enabled. https://github.com/clj-kondo/clj-kondo/issues/1514 • Add Sublime Text instructions https://github.com/clj-kondo/clj-kondo/issues/827 (https://github.com/KyleErhabor) • Fix end location in anonyous function body https://github.com/clj-kondo/clj-kondo/issues/1533 • Bump datalog-parser to 0.1.9: allows symbol constants in datalog expression #2022-01-1315:35imrewas going through the default config just now and spotted https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/config.clj#L44-L45#2022-01-1319:29borkdude@U08BJGV6E yes.. so?
#2022-01-1319:30imre:simple-libspec false is right after the map it's supposed to be in#2022-01-1319:30imreI'm guessing the new config linter would catch a similar one#2022-01-1319:31borkdudeI don't even know what this does. How do you know where it's supposed to go? ;)#2022-01-1319:32imreChecked the impl of the linter whose config is just before it#2022-01-1319:32imreAnd its indentation implies it should be in the map#2022-01-1319:33borkdudeah I see it now yes, thanks#2022-01-1319:33borkdudethe linter doesn't catch this yet, but can be made so#2022-01-1319:35imreI guess it would have caught it as an unknown linter. As of the linked commit, the key is in a position where a linter name should be#2022-01-1319:35borkdudeah yes#2022-01-1319:36borkdudelet's test it out :)#2022-01-1319:37borkdudeIt doesn't catch that specific one since the expected names are derived from this config 😂#2022-01-1319:37borkdude#2022-01-1319:38imreAah#2022-01-1319:39imreQuite the edge case 😁#2022-01-1315:08dharriganFirst release of the year, if I'm not mistaken! Here's to many more! 🙂#2022-01-1317:28Ben SlessIs there a ticket for #meander support?#2022-01-1317:30borkdude@ben.sless No, but the first reaction will be: do it as a configuration macro/hook and share it via clj-kondo.exports in the library#2022-01-1317:31borkdudeI can help with that if you want#2022-01-1317:32Ben SlessIt's incredibly complicated with a ton of syntax and binding forms, wouldn't really know where to start#2022-01-1317:32borkdudeLet's just start with an example#2022-01-1317:33Ben Sless
(m/rewrite {:a 'a :b nil :c 3}

  {:a ?a :b ?b :c ?c}
  {:a ?a
   & ~[(if ?b [:b ?b])
       (if ?c [:c ?c])]})
(rewrite expr & pairs)
#2022-01-1317:34Ben Slessleft and right pairs are handled differently, lhs introduce bindings, rhs use bindings#2022-01-1317:34borkdudewhat does the tilde mean in this context?#2022-01-1317:34borkdudeyeah, this can all be done using hooks, I'm convinced :)#2022-01-1317:35borkdudeit's pretty similar to core.match#2022-01-1317:35Ben SlessQuoting: https://github.com/noprompt/meander/blob/epsilon/doc/operator-overview.md#escaping#2022-01-1317:35Ben Slesscore.match on steroids and mutagenic agents 🙂#2022-01-1317:36borkdudehehe. ok.#2022-01-1317:36borkdudeI'll take a stab at this and you can take it further if you want.#2022-01-1317:37Ben SlessAppreciate it. If it helps, this is what this would expand to:
(let*
  [R__15723
   (let*
     [TARGET__15718 {:a 'a, :b nil, :c 3}]
     (let*
       [T__15721
        (. TARGET__15718 valAt :c)
        T__15720
        (. TARGET__15718 valAt :b)
        T__15719
        (. TARGET__15718 valAt :a)]
       (let*
         [?a T__15719]
         (let*
           [?b T__15720]
           (let*
             [?c T__15721]
             (let*
               [form__12952__auto__ {:a ?a}]
               (merge
                 (into {} cat [[(if ?b [:b ?b]) (if ?c [:c ?c])]])
                 form__12952__auto__)))))))]
  (if (meander.match.runtime.epsilon/fail? R__15723) nil R__15723))
#2022-01-1317:38Ben SlessIf there was no unquote, the code inside the vector would be quoted as symbols#2022-01-1317:47borkdude#2022-01-1317:48borkdude.clj-kondo/meander/epsilon.clj:
(ns meander.epsilon
  (:require [clojure.string :as str]
            [clojure.walk :as walk]))

(defn collect-vars [expr]
  (let [vars (volatile! [])]
    (walk/postwalk (fn [x]
                     (when (and (symbol? x)
                                (str/starts-with? (str x) "?"))
                       (vswap! vars conj x))
                     x)
                   expr)
    @vars))

(defmacro rewrite [expr & exprs]
  (let [ret `(do ~expr
                 
#2022-01-1317:48borkdude.clj-kondo/config.edn:
{:hooks {:macroexpand {meander.epsilon/rewrite meander.epsilon/rewrite}}}
#2022-01-1317:50borkdudethis should be enough to get you started. once you have complete support, you can rewrite it into a :analyze-call hook, which would take care of better locations#2022-01-1317:56Ben SlessThanks, I'll try rolling with it and see how it goes#2022-01-1317:57borkdudeThe idea is: just expand into something which makes syntactically sense, but it doesn't really have to make sense in terms of what the library exactly does#2022-01-1408:40borkdudeA new version of clojure-extras for IntelliJ was released to the marketplace (0.4.5): https://plugins.jetbrains.com/plugin/18108-clojure-extras/ It has the newest clj-kondo and fixes a couple of issues. Thank you @brcosta! If you're using the plugin, consider giving it a review on the marketplace!#2022-01-1411:39brcostaYay! Most of the issues we discussed here are now fixed (bad highlighting, linting of CLJS files, performance issues, etc) 🙂#2022-01-1412:06pfeodrippe[RESOLVED] Wanted to ask something here, it's not a feature request (for clj-kondo) or a bug, but a helper for tests (but if it's best suited for issues, I can put it there and delete it here). When creating tests, we have the lint! helper where we pass the stringified Clojure code and the config, so far so good. What I see as a disadvantage of this is that we have to be aware of column and rows (which are most of the time an implementation detail for the tests). Do we find a good idea to create some macro where we can pass real clojure code, just with a marker added in the location of the errors (like when we pass %s in format)? E.g.
(assert-errors
 config
 (inc $ (:a {:a "foo"}))
 {:message "Expected: number, received: string."})
The Clojure code we want to test is (inc (:a {:a "foo"})) , but we are passing the $ marker (it could be anything, even a call using ($ ...) to say that the next form (like a reader tag, and we could probably use a reader tag itself) is where the error is going to happen (you could have multiple $ and pass multiple errors). With this we don't need to be aware of the stringified location, the disadvantages are the weird syntax and that clj-kondo itself will mark the code with a linter error (if we don't do a hook for it, which should be pretty simple). Let me know what you think, if it's worth it, probably someone came with this before and I can also see good reasons for not to do it. I was working on https://github.com/clj-kondo/clj-kondo/issues/783 and did something (just for experimentation) at https://github.com/clj-kondo/clj-kondo/compare/master...pfeodrippe:fix-keyword-map-type-inference?expand=1#diff-2c740573fab0308a76d7982a49aab22fbb160dc460e49faa1683cf3da38dad5cR815 (see assert-errors). Will open the PR after we settle on it only o/
#2022-01-1420:20borkdude> What I see as a disadvantage of this is that we have to be aware of column and rows (which are most of the time an implementation detail for the tests IMHO). Those are not implementation details but very important. As such, I don't think this is a good idea since those need to be tested.#2022-01-1420:21borkdudeShowing the errors at the right location is one of the things clj-kondo has to get right.#2022-01-1420:22pfeodrippeYes, sure, I've thought that the location of the error was more important (instead of having to say the column/row pair), but yes, I completely understand, better to be as specific as possible. Thanks#2022-01-1420:23borkdudeif you don't care about the location of the error, you can just leave it out in assert-submaps#2022-01-1420:27pfeodrippeYes, I care about the location, just wanted to get rid of having to know the exact column number of the string by putting a marker instead.#2022-01-1420:30pfeodrippeThanks for the answer, Michiel o/ I will resolve this thread#2022-01-1709:26borkdudeHopefully, if nothing comes up, I'll get back to your PR hopefully on Wednesday or Thursday About the above btw, I usually produce the data that goes into assert-submaps by doing (prn (lint! ...)) first and then checking that in.#2022-01-1712:33pfeodrippeThanks. I have been able to be successful by using analyze-call for the keyword call (besides calling lint-keyword-call!) and by adding some metadata to the return data. I was thinking if we could add some key representing a dynamic return type (which keywords calls are) with a function as the value so when resolving in the linter, the resolver calls this function and has the tag returned. Let's see if it works. I will let you know when you can review the approach again o/ l#2022-01-1712:36borkdudeThank you! As a first issue this isn't an easy one but I appreciate it a lot. It may take some time from my side to get this merged as this is quite involved and I need to dedicate some time to it.#2022-01-1712:37pfeodrippeSure! It's a linter I use everyday and I would not like to see lots of regressions caused by myself ahahhahaa#2022-01-1420:15seancorfieldIs this a (known) bug?
(ns ws.web.newrelic
  (:require [clojure.string :as str])
  (:import (com.newrelic.api.agent NewRelic Trace))) ; <= Trace flagged as unused import
...
(defprotocol Handler
  "Dummy protocol just to provide a basis for the defrecord below.
  The record encapsulates a Ring handler and provides a traceable
  entry point for New Relic. {:dispatcher true} tells New Relic to
  start a transaction at this point, if none is already in effect."
  (handle [this req] "Handle a Ring request."))

(defrecord NewRelicHandler [handler]
  Handler
  (^{Trace {:dispatcher true :transactionType "web"}} handle [this req] ; <= Trace used here as a Java Annotation
   (handler req)))
#2022-01-1420:17borkdudeI think you're hitting an edge case there in that clj-kondo doesn't register the usage from metadata keys or so#2022-01-1420:17borkdudeIssue welcome#2022-01-1420:22borkdudeyou can work around this by just using the class on the top level or so, or using #_:clj-kondo/ignore#2022-01-1420:25seancorfieldI haven't had to touch this file in ages so it's not important. In fact, I opened it by mistake today 🙂 But I will create an issue with that code in it.#2022-01-1420:26borkdudeThanks!#2022-01-1420:32seancorfieldhttps://github.com/clj-kondo/clj-kondo/issues/1540#2022-01-1420:32seancorfieldLMK if you need any additional info.#2022-01-1420:33borkdudeThat should do it, thanks#2022-01-1500:05EugenI'm looking to add a linter for a macro proxy+ - https://github.com/redplanetlabs/proxy-plus . The macro is used to extend java abstract classes. Any hints on how to approach this ? Where can I publish the linting so it's usable by other people when it's done? Sample code: https://github.com/ieugen/ofbiz-tooling-ro/blob/main/development/src/dev/schema.clj#2022-01-1500:06EugenThere is also this https://github.com/redplanetlabs/proxy-plus/issues/14#2022-01-1500:21Eugenfound https://github.com/clj-kondo/config#2022-01-1500:58EugenSeems lint-as works in getting rid of the warnings - will see how this behaves in the future:
(ns dev.schema
  {:clj-kondo/config '{:lint-as {com.rpl.proxy-plus/proxy+ clojure.core/proxy}}}
#2022-01-1501:08EugenIs there a rule for unused this in reify ? I would like to ignore them. Perhaps I can use _#2022-01-1501:11Eugen_ seems to work ok. I'm good, sorry for using Slack as my rubber duck#2022-01-1501:55Alex Miller (Clojure team)this is just a convention, you can call it whatever#2022-01-1507:30borkdude@eugen.stan you can start any name with an underscore, like _this to get it ignored #2022-01-1507:31borkdudeThere is an issue about an option for ignoring the self referring local automatically, feel free to upvote#2022-01-1510:47Eugenthanks. I will check it out. lint-as for proxy+ does not work that great. hides errors for undefined symbols inside the construct. any hints on how should I go by implementing linting for this? it'similar to reify and proxy, I could not find how those are implemented though#2022-01-1510:48borkdude@eugen.stan You can support any macro by writing a hook for it. The :macroexpand hook is the easiest as you can just place a simplified macro in your config.#2022-01-1510:49borkdudeIf you have an example of this proxy+ macro I can help you get going.#2022-01-1510:49borkdudeAn alternative is to just turn off unresolved symbols in calls to proxy+#2022-01-1510:50borkdude
:unresolved-symbol {:exclude [(com.rpl.foobar/proxy+)]}
#2022-01-1510:50EugenI tried ignore and clj-kondo threw error#2022-01-1510:50Eugenbut syntax was not like above, will try again#2022-01-1510:51EugenI have a link to my github above, with code image that shows how I use it#2022-01-1510:51Eugenlatest commit should contain limiting rule I used#2022-01-1510:53borkdudeok, let's continue in a thread. I'll check out the code and take a look#2022-01-1510:54Eugenthanks, the difficult part IMO is that it references methods from classes and interfaces and that could be anything#2022-01-1510:54borkdudedo you have a link to the exact file and line where this is used?#2022-01-1510:55Eugenso a lint-as reify might work for each case where it's implementing an interface or class#2022-01-1510:55borkdudeI don't get any errors in this code linked before#2022-01-1510:55Eugenyes, above but can't copy paste it on phone#2022-01-1510:55Eugenit's schema.clj#2022-01-1510:56Eugenin my post from earlier#2022-01-1510:56borkdude
$ clj-kondo --lint development/src/dev/schema.clj
development/src/dev/schema.clj:151:24: warning: unused binding parent-schema
development/src/dev/schema.clj:151:46: warning: unused binding name
development/src/dev/schema.clj:151:56: warning: unused binding operand
linting took 59ms, errors: 0, warnings: 3
#2022-01-1510:56borkdudecommit: 61cf0b033e49d278fb841e86bee3cda694ae2e41#2022-01-1510:57Eugenlet me go to computer#2022-01-1511:00Eugenyes, but if I change line 124 to len (- (count undefined-symbol) 1) and run linting I get the same errors as above#2022-01-1511:01Eugenthat is inside reify org.apache.calcite.linq4j.Enumerator of enumerator method of proxy+ AbstractEnumerable#2022-01-1511:02borkdudeI changed that, but I don't see an error. Are you sure this error is coming from clj-kondo and not from some other tool?#2022-01-1511:02Eugenthat is the issue, IMO, we SHOULD get an error and we don't#2022-01-1511:03borkdudeaha#2022-01-1511:03Eugenundefined-symbol is clearly undefined#2022-01-1511:03Eugenmaybe it has to do with nesting ?!#2022-01-1511:04borkdudeYes, this is not an issue with your config, it's an incompleteness in clj-kondo which can be improved. Proxy is one of the few things that I kept postponing to support fully ;)#2022-01-1511:04borkdudeFeel free to post an issue. You can reproduce this with normal clojure proxy as well#2022-01-1511:05Eugenok, will do#2022-01-1511:05Eugenthanks for looking into this#2022-01-1511:05Eugenbug report of feature request 🙂 ?#2022-01-1511:07borkdudeeither is fine ;)#2022-01-1511:07borkdudeglass half full or empty? ;)#2022-01-1511:18Eugenthe issue is here https://github.com/clj-kondo/clj-kondo/issues/1544#2022-01-1511:19EugenI've notived reify and proxy are quite different IMO - since they work with classes and interfaces and introduce a lot of symbols. Are there building blocks in clj-kondo for dealing with that?#2022-01-1511:20Eugenor we need something new to support those?#2022-01-1511:21borkdudeMost of the code supporting those things is in clj_kondo/impl/analyzer.clj#2022-01-1511:21borkdudesee the giant case statement in analyze-call and follow from there#2022-01-1511:24Eugenthanks, I'll probably take a look this week. btw, cool stuff with nbb. I did a bit of work on https://github.com/titonbarua/shadow-cljs-gjs-target . Maybe I will have some time to continue and have something similar for Gnome desktop - uses gjs#2022-01-1511:25borkdudeOh, that's cool :) There is #nbb but also #obb which is for macOS JXA which I believe is similar to the Gnome stuff, maybe#2022-01-1511:25borkdudeso maybe we can have #gbb soon ;)#2022-01-1511:25Eugenthanks, yeah I was thinking about obb - but naming colided in my head#2022-01-1511:26Eugenmaybe gbb (gnome babashka )?#2022-01-1511:27borkdudeyes, that's what I said above :)#2022-01-1511:27EugenI missed that - I was typing 🙂#2022-01-1511:28borkdudemultitasking is hard. now that I have windows + WSL2 + wslg I can easily try this gjs stuff out I think#2022-01-1511:29borkdudewhat's the status of gnome? isn't it a bit old/deprecated in favor of other stuff in the coming years? or it's not going away soon?#2022-01-1511:30borkdudeanyway, feel free to experiment with obb -> gbb and perhaps it can join the babashka org if you think it's a useful thing :)#2022-01-1511:31Eugenno, it's here to stay. Ubuntu moved back to shipping with Gnome after they tried Unity#2022-01-1511:31borkdudeI heard gnome plugins are quite notorious in that they are single threaded and can crash gnome?#2022-01-1511:31EugenWayland is getting some traction to replace ancient http://X.org#2022-01-1511:32Eugenyes, not the best situation - happened to me quite a few times.#2022-01-1511:32EugenGnome 40 came out last year and they promissed they are taking more care of plugin compatibility and stability#2022-01-1511:33borkdudeperhaps https://www.npmjs.com/package/node-gtk can also be used with #nbb already, or something else on node#2022-01-1511:33Eugenhttps://www.phoronix.com/scan.php?page=news_item&amp;px=GNOME-40-Better-Extensions#2022-01-1511:34Eugenyeah, I'll see if I have some time to look at those as well#2022-01-1511:34borkdudeok, but it's good to hear gnome is not going anyway, then gbb might be a good idea :)#2022-01-1511:34Eugenbut right now I'm happy I managed to implement Calcite over XML#2022-01-1516:17borkdudeQuick follow-up bugfix release to the previous one: clj-kondo 2022.01.15 • Fix https://github.com/clj-kondo/clj-kondo/issues/1537: stackoverflow with potemkin import vars with cyclic references • Fix https://github.com/clj-kondo/clj-kondo/issues/1545: `recur` in `cond->` gives warning about `recur` not in tail position. • Fix https://github.com/clj-kondo/clj-kondo/issues/1535: support CLJS vars / protocols references via dot rather than slash.#2022-01-1615:10lispers-anonymousI am attempting to write a custom clj-kondo hook. I have a token node that is a symbol that looks like foo/bar such that foo is an alias for another namespace like some-library.api.foo . Is there a way I can get the information to fully expand that namespace part of the symbol, so that I now have some-library.api.foo/bar as the symbol?#2022-01-1615:13borkdude@UDVJE9RE3 currently not, but could you describe the macro a little bit? usually macros don't need to resolve alias, they just emit#2022-01-1615:17lispers-anonymousI'm not doing anything with a macro. Here is the hook setup in my config.edn :hooks {:analyze-call {re-frame.core/reg-event-fx lispers-anonymous.re-frame.sub-in-event-handler/hook}} I'm trying to emit a warning when some calls re-frame.core/subscribe inside of a re-frame event.#2022-01-1615:17borkdudeah gotcha#2022-01-1615:17borkdudecurrently not possible, but feel free to post an issue#2022-01-1615:21lispers-anonymousSure I can do that. This is not something blocking me up, as the project I'm hoping to use this in is pretty consistent in the namespaces it uses. Turing on the :consistent-alias in conjunction with my current hook, and explicitly checking for the symbol rf/subscribe will be more than enough.#2022-01-1615:21borkdude:-)#2022-01-1615:53lispers-anonymousThanks for the quick response this morning. I opened up an issue here: https://github.com/clj-kondo/clj-kondo/issues/1546#2022-01-1717:32wilkerluciohello, I'm using kondo in a project with Clojure 1.11, but Kondo seems to not be aware of new clojure core fns like update-keys, using Kondo 2022.01.15, is there a way to make kondo aware of those? or need to ignore?#2022-01-1717:33borkdudekondo should be aware of this:
$ clj-kondo --lint - <<< 'update-keys'
linting took 40ms, errors: 0, warnings: 0
but your cache might be stale from before you upgraded to 11
#2022-01-1719:46wilkerlucioyeah, thanks, I had tried to clean kondo cache and re-process it, the issue was that I haven't deleted my .cpcache and it ended up rebuilding with the previous cpcache which pointed to Clojure 1.10 facepalm#2022-01-1719:47wilkerluciohumm, actually I though that was the problem, but I'm having the issue with update-keys after all these deletes and rebuilds#2022-01-1719:48borkdudethen are you sure you're linting with clojure 11?#2022-01-1719:48borkduderepro welcome ;)#2022-01-1719:49wilkerluciothanks, looking deeper, for some reason my CP is still using Clojure 1.10, gonna debug futher to understand it, thanks for hanging around 🙂#2022-01-1717:34borkdude
clj-kondo --lint $(clojure -Spath) --dependencies 
should fix that
#2022-01-1803:17dpsuttonI’m parsing the output of clj-kondo to make a dashboard. One thing I’ve noticed is the message for unused binding and unresolved var are close but slightly different, missing a ::
warning: Unresolved var: Metric
warning: unused binding query
It would make it easier to parse if this was consistent and was Unused binding: query I think
#2022-01-1803:26dpsuttonor another way is if there was an argument that would have clj-kondo --lint --print-lint src and the output would be
src/metabase/util/urls.clj:22:20: warning: unresolved-var: Unresolved var: public-settings/site-url
and unresolved-var the linter is included in the output. Would make some dashboarding a bit easier to categorize how many errors of each type there are.
#2022-01-1806:51borkdudeWhy not use the JSON or EDN output?#2022-01-1806:51borkdudeAnd feel free to report the missing location issue with a repro#2022-01-1806:52borkdudeWe could make linter messages more consistent. Feel free to make a separate issue for that #2022-01-1806:57dpsuttoni was checking clj-kondo --help and didn't see those options for JSON or EDN#2022-01-1807:02borkdudeThose options are available under output in config, see config.md#2022-01-1807:03borkdudePerhaps we should support those command line flags though #2022-01-1807:03borkdudeIssue welcome as well #2022-01-1807:04dpsuttoni was able to work around it. I'll wait until we chat more in depth. was just trying to get a dashboard up with some metrics around all of our warnings#2022-01-1807:04dpsuttonit came out pretty well. Have a dashboard in metabase about warnings in metabase 🙂#2022-01-1807:04borkdudeAwesome 👏 #2022-01-1814:42Michaël SalihiHello, I get this error error: update-in with single key with this function for the second arity %2:
(defn update-vals [m v f]
  (reduce #(update-in % [%2] f) m v))
#2022-01-1814:55mynomotoThe message is saying that you could use (update % %2 f) instead.#2022-01-1814:57borkdudeindeed#2022-01-1814:57Michaël SalihiYes I understand that, but in my case I use only this function with multiple keys so I want to avoid any condition here. Thanks.#2022-01-1814:59borkdudeIf others are reading: this not an error by default, but a warning, just to be clear. the linter is also optional (off by default). The way you write it above, update-in is always called with a single key, the %2 argument is the key, not multiple keys, no matter what the value of %2 is.#2022-01-1815:02borkdudeYou can ignore any error with #_:clj-kondo/ignore but it doesn't make sense to ignore this, clj-kondo is correct in this case.#2022-01-1815:03borkdudeThe %2 isn't spliced into your vector.#2022-01-1815:03Michaël SalihiYes understand, thanks @U04V15CAJ So to pass the CI tests for my current project, I have no choice to update my function and use condition against the argument to use either update or update-in, right?#2022-01-1815:04borkdudeno...#2022-01-1815:04Michaël Salihi> You can ignore any error with #_:clj-kondo/ignore but it doesn't make sense to ignore this, clj-kondo is correct in this case. Agree. I don't want to do that and affect all devs of the project just for this function 🙂#2022-01-1815:04borkdude(update-in %1 [%2] ...) is the same as (update %1 %2 ...) always#2022-01-1815:05borkdudeno matter what the values of those arguments are#2022-01-1815:05borkdudethis is what clj-kondo is trying to say to you :)#2022-01-1815:06Michaël SalihiAlright! 👍 Thanks to you and clj-kondo!#2022-01-1815:07borkdudeso yes, you should update your function, but no, you don't have to introduce conditions against the arguments#2022-01-1815:09Michaël SalihiYes perfect, I end up with this function:
(defn update-vals [m v f]
  (reduce #(update %1 %2 f) m v))
And thanks to clj-kondo, now it's clean.
#2022-01-1814:46Michaël SalihiCan we ignore this error only for this case? Without changing Kondo config file?#2022-01-1814:51Noah BogartWhat happens if you change % to %1?#2022-01-1814:58Michaël SalihiThanks for the suggestion. Same error.#2022-01-1814:58Noah Bogartcool, sorry it didn’t help#2022-01-1815:24seriogaHallo Michiel. Is this ticket buried? https://github.com/clj-kondo/clj-kondo/issues/801#2022-01-1815:25borkdudeClosed due to inactivity, but feel free to respond and I'll re-open#2022-01-1815:30borkdudeJust a message like "I'm still interested" suffices#2022-01-1815:38seriogaMichiel, what about this (not mine) ticked? Is it OK that it is automatically closed? https://github.com/clj-kondo/clj-kondo/issues/1179#2022-01-1815:40borkdudeFeel free to respond the same way#2022-01-1817:45jumarI'm thinking about making an automated test that would check if no namespaces outside of a particular package use namespaces inside that package. I'm looking at clj-kondo's :namespace-usage for this. Does it make sense to you? What about the performance? Note: I haven't used clj-kondo programatically yet, only (sporadically) as a command line tool and in Emacs#2022-01-1818:19borkdude@jumar Yes, you can do this using the analysis data. Performance: just lint your own sources, should not take too long (depending on the size of your project of course...). If you lint all dependencies then it will take longer.#2022-01-1818:45jumarPerfect, thanks!#2022-01-1910:14jumar@U04V15CAJ This takes about 4 seconds on my project (~30K lines of Clojure code, ~300 files)
;; this can take about 4 seconds
  (time (def analysis (clj-kondo/run! {:lint ["src"]
                                       :config {:output {:analysis true}}})))
Would you say that's expected running time?
#2022-01-1910:28borkdudeI would say so, are you disappointed? ;)#2022-01-1910:30jumarNot that much - I wish it was even faster but I think this is good enough for me right now 🙂#2022-01-1910:32borkdudeYou can also use tools.namespace directly if you're only interested in namespace dependencies. That will be much faster since it only reads the top level ns form#2022-01-1911:26borkdudeAnnouncement! clojure-extras, an IntelliJ plugin which brings clj-kondo + inline-eval to Cursive, v0.5.0! https://plugins.jetbrains.com/plugin/18108-clojure-extras/https://t.co/SxPSepJaJb It now has an option to analyze the classpath with clj-kondo for better linting results, and more! Join the #clj-extras-plugin to discuss the plugin in detail.#2022-01-1919:27emccueDoes this provide support for hooks in any way? Like could i teach cursive about my macros now, or is that functionality still requiring clojure-lsp#2022-01-1919:27borkdudeyes, supported#2022-01-1919:28borkdudeas far as linting is concerned. navigation etc is still isolated in cursive itself#2022-01-1919:28emccuei’ll need to try it out. that could be a game changer#2022-01-1919:41sashtonI have a library which defines some resources/clj-kondo.exports. In a separate application, which uses that library as a dependency, after clojure-lsp initializes and runs clj-kondo stuff I end up with a .clj-kondo/my.lib folder. However, I don’t have a .clj-kondo/config.edn in my application, nor in my ~/.config/clj-kondo directory. It was my impression that a config.edn containing a {:config-paths ["my/lib"]} would be required to pull in the lib’s stuff. Does clj-kondo scan the classpath automatically for resources/clj-kondo.exports` directories, and import them automatically?#2022-01-1919:43borkdude@sashton clojure-lsp runs clj-kondo with --copy-configs while linting your classpath, this is why it copies them to your local config. it also creates a .clj-kondo dir if doesn't exist yet. in recent versions, clj-kondo automatically loads the exported config from your config dir, so there is no need for :config-paths anymore for exported configs.#2022-01-1919:44sashtonSo it sounds like I won’t need to use config-paths in this case? Or is config-paths for a separate use-case?#2022-01-1919:44borkdudefor this case you don't need it, you may still need it in some cases, e.g. when exporting a config for your own library and you would like to use it in linting for the same project#2022-01-1919:45borkdudehere is an example of that: https://github.com/Engelberg/better-cond/blob/master/.clj-kondo/config.edn#2022-01-1919:45sashtonmakes sense, thanks!#2022-01-2111:19seriogaHallo Michiel. Do we have somewhere a linter idea for the (:refer-clojure :exclude [something]) if there is no something in the namespace and :exclude is redundant?#2022-01-2111:21borkdudeno, but I think that is a good idea, maybe :unused-refer-exclude or so#2022-01-2111:22seriogaIt is very good idea, otherwise I have redundant excludes after refactoring 🙂#2022-01-2111:22seriogaShould I file a ticket?#2022-01-2111:22borkdudeyes, please 🙏#2022-01-2111:25borkdudemaybe :redundant-refer-exclude is a better name indeed, since you don't really "use" them#2022-01-2111:29seriogaFiled https://github.com/clj-kondo/clj-kondo/issues/1552#2022-01-2112:51Giorgio Valoti👋 Hello folks. I’m trying to confirm this behaviour with clj-kondo. This should be a reproducible example:
(defn- my-private-fn [])

  (defmacro my-with-redefs
    [bindings & body]
    `(clojure.core/with-redefs ~bindings (f#)
       
In other words, I would like clj-kondo to ignore the usage of my-private-fn but it doesn’t, presumably because of macro machinery?
#2022-01-2112:54borkdudeI don't see the error in this specific example, but I do when I refer to the private var from another ns. Is that what you mean?#2022-01-2112:55borkdude
(ns foo)
(defn- my-private-fn [])

(defmacro my-with-redefs
  [bindings & body]
  `(clojure.core/with-redefs ~bindings (f#)
     
#2022-01-2112:58borkdudeI don't know why the error isn't gone with the annotation, I think that's a bug. Please file an issue. But you can ignore the warning by writing:
(foo/my-with-redefs [#'foo/my-private-fn (constantly :ok)]
                (+ 1 2))
#2022-01-2115:46Giorgio ValotiYes, the fn was in another namespace#2022-01-2115:47Giorgio ValotiThanks @borkdude I’ll file an issue asap 🙂#2022-01-2113:17Michaël SalihiHello guys! I wonder to know what's the best solution to avoid shadowed var in a let destructuring form? Currently I destructuring a JS object which contains key that shadowed clojure.core/key:
(map #(j/let [^:js {:keys [x y height width color data key]} %
              ...]
#2022-01-2113:18Michaël SalihiOf course, I can do something like:
(map #(j/let [^:js {:keys [x y height width color data] :as bar} %
              current-key (:key bar)
              ...]
#2022-01-2113:20borkdude@admin055 You can avoid it with explicit named keys destructuring:
{my-other-key :key
:keys [x y z]
}
#2022-01-2113:21borkdudebut your method of course works too#2022-01-2113:22Michaël SalihiPerfect, I forgot the syntax, this is what I was trying to do. Thanks @borkdude!#2022-01-2115:31seriogabtw, Clojure Extras does not lint my code with built-in clj-kondo anymore. It was installed from the file firstly (and worked), then disabled (because too annoying), then enabled after installing from marketplace (and upgraded twice) — and it does not lint anymore. Removed then installed again — no changes. simple_smile#2022-01-2116:06brcostaHi, would you mind opening an issue here? https://github.com/brcosta/clj-extras-plugin. It’d help if you can add the versions (intellij, cursive, extras) so that I can also test it here). Thanks 🙂#2022-01-2208:56seriogaHi Bruno. https://github.com/brcosta/clj-extras-plugin/issues/11#2022-01-2115:39borkdude@serioga please report in #clj-extras-plugin#2022-01-2115:39borkdudeand maybe tag @brcosta there#2022-01-2123:27Karol WójcikGot a very bizzare issue cc @borkdude. Here is a minimal reproduction. 1. Define file core.clj
(require '[malli.core])
(require '[malli.experimental])
(require '[potemkin :as pot])

(pot/import-vars [malli.core [form schema =>]
                  malli.experimental [defn]])
2. Run.
clj-kondo --lint core.clj
3. Result:
core.clj:6:1: warning: redefined var #'user/
linting took 7ms, errors: 0, warnings: 1
clj-kondo v2022.01.15
#2022-01-2209:22borkdudeI will take a look#2022-01-2209:26borkdudeThis works for me:
(ns foo (:refer-clojure :exclude [defn]))

(require '[malli.core])
(require '[malli.experimental])
(require '[potemkin :as pot])

(pot/import-vars [malli.core form schema =>]
                 [malli.experimental defn])
#2022-01-2209:26borkdudeyou shouldn't nest the imported vars in a separate vector I think#2022-01-2209:41borkdudenonetheless, the error message could be better here, feel free to post an issue about this#2022-01-2211:05Karol WójcikThank you for correcting me! My bad! 🙂#2022-01-2220:42mknoszligsneak preview of task cycle detection in babashka’s bb.edn#2022-01-2220:47borkdude@maximilian Awesome!#2022-01-2220:48mknoszligi’m not sure yet whether it’s better to show the same order in the cycle path (as above), or make it relative to the currently highlighted task#2022-01-2220:49mknoszligalso: currently only detects one cycle at a time if there’s more than one#2022-01-2220:49borkdudejust the first cycle is enough#2022-01-2220:50borkdudeI think it would be the most logical to show the cycle starting with the task you are in?#2022-01-2220:50borkdudebut it's not that important, as long as you see a cycle warning#2022-01-2220:51mknoszligi think that wouldn’t be too much additional work#2022-01-2220:52borkdude
b {:depends [^here]}
would warn about cycle b -> ...
#2022-01-2220:54mknoszligyep, basically just anchoring the displayed path on the “active” task. my only concern is that if it’s used in another mode than interactive it’ll be harder to identify as essentially the same warning?#2022-01-2220:55borkdudeoptimize for editor experience I would say#2022-01-2220:55borkdudepeople are going to look into the code anyway to see what's wrong#2022-01-2220:56mknoszligtrue. i’ll give it a shot. thanks for the feedback 🙂#2022-01-2319:54borkdude#2022-01-2321:28berkeleytrueI have a cljs file that wraps a javascript library. I'm using a macro to dynamically generate the functions. When I require those generated functions, clj-kondo complains that those variables are unresolved. Is there a way in my clj-kondo configuration to tell it the methods it exports? macro in question: https://github.com/BerkeleyTrue/crypto-egg/blob/master/src/chalk/macro.cljc#L18#2022-01-2321:40borkdudedo you have an example call of this macro?#2022-01-2321:40borkdudeand example calls of those functions? then I might be able to say yes or no, or it depends#2022-01-2321:45berkeleytrueHere is the call https://github.com/BerkeleyTrue/crypto-egg/blob/master/src/chalk/core.cljs#L7#2022-01-2321:46berkeleytrueoops, that is the macro call. Here is the method calls https://github.com/BerkeleyTrue/crypto-egg/blob/master/src/server/infra/timbre.cljs#L8#2022-01-2321:46berkeleytrueanother call https://github.com/BerkeleyTrue/crypto-egg/blob/master/src/server/infra/middlewares/logging.cljs#L34#2022-01-2321:47borkdudeok, so each method, represented as keyword, becomes a var right?#2022-01-2321:48berkeleytrueYes the key becomes the function name in a defn (defn (symbol (name :some-key...#2022-01-2321:49borkdudethis is doable. you will have to write a macro in the .clj-kondo directory for this, using the :macroexpand option#2022-01-2321:49borkdudeSee https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand#2022-01-2321:50borkdudeThe macro in the .clj-kondo dir can be a simplified one, e.g you just map over the keywords, turn them into symbols and produce a declare call#2022-01-2321:51borkdude
(deffoo chalk :foo :bar) -> (declare foo bar)
#2022-01-2321:55borkdudeUnrelated, since you're using Node.js, you might be interested in doing little scripts with #nbb https://github.com/babashka/nbb/tree/main/examples/chalk#2022-01-2322:46berkeleytrueOh sweet! it worked. For those interested https://github.com/BerkeleyTrue/crypto-egg/blob/master/.clj-kondo/chalk/macro.clj#L3#2022-01-2322:47berkeleytrue@U04V15CAJ thanks for your help! I appreciate it. Also, neat (regarding nbb)! Definitely excited for that.#2022-01-2407:50Chris McCormickwhat would be the best way to lint-as applied-science.js-interop/let as let? a form looks like this:
(j/let [^:js {:keys [velocity position uuid]} b] {:velocity velocity :position position :uuid uuid})
clj-kondo complains about velocity being an unresolved symbol.
#2022-01-2407:51Chris McCormickIt's not exactly let obviously because of the ^:js thing#2022-01-2408:02borkdudeWhat have you tried? :lint-as clojure.core/let would work I think #2022-01-2408:26Chris McCormickok let me try again#2022-01-2408:29Chris McCormickok yes sorry that works. i am probably doing something unclever but i am seeing this for the :lint-as declaration in the require block: > warning: Unresolved namespace applied-science.js-interop. Are you missing a require?
(ns smash.physics
  {:clj-kondo/config {:lint-as {applied-science.js-interop/let clojure.core/let}}}
  (:require
    [sitefox.ui :refer [log]]
    [applied-science.js-interop :as j]
    ["matter-js/build/matter" :as Matter]))
#2022-01-2408:34borkdude@chris358 Put a quote in front of the lint-as map#2022-01-2408:35borkdudeso like:
(ns smash.physics
  {:clj-kondo/config '{:lint-as {applied-science.js-interop/let clojure.core/let}}}
  (:require
   [sitefox.ui :refer [log]]
   [applied-science.js-interop :as j]
   ["matter-js/build/matter" :as Matter]))

(j/let [x 1])
#2022-01-2408:36Chris McCormickthank you#2022-01-2500:34JRI found https://www.braveclojure.com/writing-macros/
(ns macro-test.core)


(defn criticize-code [criticism code]
  `(println ~criticism (quote ~code)))

(defmacro code-critic
  [good bad]
  `(do 
clj-kondo highlights the (1 +1) part as an error. From my very limited understand of macros, (1 + 1) should be ignored since it’s in a syntax quote. Is this the sort of thing I’d have to fix with a hook?
#2022-01-2509:23borkdude@john.t.richardson.dev That's the sort of thing you could fix with a hook, but there are other options as well#2022-01-2510:28dharriganAt work we use (for better or worse) timbre as a logging library. I notice in impl/analyzer.clj there are is a check at lines 2033-2039 for analyzing clojure.tools.logging infof debugf etc., Considering that timbre is a popular library for logging, would you be open to a PR that also adds taoensso.timbre/infof debugf etc... for those to be included in analysis?#2022-01-2510:29borkdudeI'd like to support this via hooks if possible. The built-in support for many libraries came from a time when hooks didn't exist yet.#2022-01-2510:30dharriganAh yes, of course, since you would have to bring in the dep, right? in deps.edn#2022-01-2510:32borkdudeHooks don't need the dep, but I think it's better if support for libraries are built using hooks, since they can evolve independently from the installed clj-kondo version and can be maintained by others than me as well#2022-01-2510:33borkdudePerhaps for now you could also use :lint-as for those macros#2022-01-2510:33borkdudeif the syntax is similar#2022-01-2510:33dharriganYes, very similar and yup easy enough to add that 🙂#2022-01-2510:33dharriganAlso, doing a hook might be fun little thing to do eventually in my spare time 🙂#2022-01-2510:34borkdudeIf it can be done using :lint-as that would be my preference#2022-01-2510:34borkdudehooks are cool, but usually only needed for macros that have a non-standard syntax compared to core ones#2022-01-2510:34dharriganyes, that sounds best#2022-01-2510:34dharriganjust trying it out#2022-01-2510:38dharriganYup, works grand#2022-01-2510:39dharrigan#2022-01-2610:08borkdudeImpressive work by @pfeodrippe Map keyword inference. Still reviewing PR.#2022-01-2621:24fadrianI have one macro defined and used many times in one file that is throwing large numbers of "Unresolved symbol" warnings from clj-kondo. According to the documentation, one can configure clj-kondo with namespace local config using `:clj-kondo/config` metadata in the namespace form. Is there an example of how to do this anywhere on the web? I've searched and can't seem to figure out where/how to put this metadata so it would effect the throwing of these warnings.#2022-01-2621:45borkdude@U0DTU8J83 here is an example: https://clojurians.slack.com/archives/CHY97NXE2/p1643013321253200#2022-01-2621:56fadrianThank you.#2022-01-2621:56borkdudeSure thing,. Let me know if you have any further questions. There's probably an even better solution for your macro, so if you give me some details, perhaps I can help you with that.#2022-01-2622:12fadrianThe macro gets passed a set of binding vars that get used in a let in the body of the macro. Each variable in the binding form generates one of the unresolved-symbol messages. In case it helps, here is the macro:
(defmacro expand [tag pnames err-check-fn err-check-msg fmt & fmt-args]
  `{~(keyword tag) {:exp-fn 
                    (fn [~'ss ~'rw]
                      (let [~pnames (:params ~'rw)]
                       (if (not (~err-check-fn ~'rw))
                         [(error (~err-check-msg ~'rw))]
                          ((partial pp/cl-format nil ~fmt) 
#2022-01-2622:13borkdudedo you mean ss and rw?#2022-01-2622:16borkdudeI think you could pretty much paste this macro in a file called .clj-kondo/macros.clj and then add this to your configuration in .clj-kondo/config.edn
{:hooks {:macroexpand {foo.bar/expand macros/expand}}}
You will have to fully qualify pp/cl-format to clojure.pprint/cl-format
#2022-01-2622:17fadrianNo - it's complaining on the variables that get passed into pnames. Here's an example use of the macro:
(expand
             "Eligibility Gate"
             [coveragePeriod maxGaps maxGapDays type class]
             #(= 5 (count (:params %)))
             #(pp/cl-format nil "Wrong number of parameters in definition of ~a." (stringify (:name %)))
             "define ~a: ~a(~a, ~a, ~a, ~a, ~a)"
             (stringify (:name rw)) (stringify (:fn rw)) coveragePeriod maxGaps maxGapDays (unstring-null (s/lower-case type) "String") (unstring-null (s/lower-case class) "String"))
Its warning about the symbols coveragePeriod, maxGaps, maxGapDays, type, and class.
#2022-01-2622:20fadrianI'm also using deps.edn, if that makes any difference in the configuration.#2022-01-2622:25borkdudeok, try the macro suggestion or else you can use the config for unresolved-symbol. the docs are here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#unrecognized-macros#2022-01-2622:27fadrianThanks again.#2022-01-2713:32pinkfrogHi. Is there some doc on something like: https://github.com/seancorfield/next-jdbc/blob/9433b86b7120555bd5b127139eec4ba80eded40e/resources/clj-kondo.exports/com.github.seancorfield/next.jdbc/hooks/com/github/seancorfield/next_jdbc.clj#L4. so that I can instruct clj kondo to correctly treat my macro?#2022-01-2713:33borkdudedocs are here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2022-01-2713:33pinkfrogYup. Just found out it too. Thanks#2022-01-2713:34pinkfrogI remember previously the doc mentions next.jdbc and now that piece is missing. Maybe my memory is wrong.#2022-01-2713:35borkdudedon't remember that#2022-01-2714:23pinkfrogI am importing java.sql.Savepoint but I’d like to use java.sql.Savepoint as the fullname instead of only Savepoint. Clj-kondo is now complaining unused import of java.sql.Savepoint.#2022-01-2714:23pinkfrogIs it a Bug?
#2022-01-2714:24Alex Miller (Clojure team)you don't need to import if you're using the full name#2022-01-2714:25Alex Miller (Clojure team)import just makes Savepoint resolve to java.sql.Savepoint, it's not actually need to cause loading or anything#2022-01-2714:25pinkfrogI suspect I shall manually import the java class first for the JVM to load it.#2022-01-2714:25Alex Miller (Clojure team)no, you don't need to do that#2022-01-2714:26Alex Miller (Clojure team)it's different than require#2022-01-2714:26pinkfrogCool. Thanks.#2022-01-2714:27pinkfrogJust to make sure, the JVM loads the java.sql.Savepoint only when I use it, right? And this magic is performed by clojure runtime under the hood.#2022-01-2714:28Alex Miller (Clojure team)yes#2022-01-2714:28Alex Miller (Clojure team)when you need the Class object it will be loaded#2022-01-2714:29Alex Miller (Clojure team)(and import does not load)#2022-01-2714:29borkdude> when I use it, right Slight clarification: it's being loaded when the compiler resolves the class name, not when the interop on that class is actually executed.#2022-01-2714:32borkdudeSo when you have a file like:
(ns foo) java.sql.Savepoint (defn foo [])
and you load that namespace, then the class is also loaded
#2022-01-2720:55borkdudeOK, this cool PR by @pfeodrippe was just merged to master. clj-kondo should now be able to infer some more type-related errors with (nested) maps. As this was a non-trivial commit, please lint your sources and report any regressions :) You can do so with:
clojure -Sdeps '{:deps {clj-kondo/clj-kondo {:git/url "" :git/sha "bcad7ea524d0c706c77610c829298a118220ee29"}}}' -M -m clj-kondo.main --lint src
(replace src with your source(s))
#2022-01-2721:20pfeodrippeYou did all the grunt work in the end, thanks, man o/#2022-01-2721:22mknoszligi’m guessing this is out of scope for the PR, right?
(let [{:keys [c]} {:c :f}]
  (inc c))
#2022-01-2721:48borkdudethat would would be a good one to support as well#2022-01-2721:49borkdudeI guess we could treat {:keys [c]} as (:c ...) and then continue with the code as usual#2022-01-2721:49borkdudeissue (+ PR) welcome#2022-01-2809:50borkdudehttps://twitter.com/borkdude/status/1486999602175827968#2022-01-2721:59Joshua SuskaloJust as a heads up, I'm getting this error on clj-kondo 2022.01.15
Suspicious state from syntax checker clj-kondo-cljc: Flycheck checker clj-kondo-cljc returned 2, but its output contained no errors: /home/jsusk/Programming/Projects/Clojure/farolero/src/cljc/farolero/core.cljc::: warning: Missing catch or finally in try
linting took 167ms, errors: 0, warnings: 1

Try installing a more recent version of clj-kondo-cljc, and please open a bug report if the issue persists in the latest release.  Thanks!
when running on my project farolero. It is correct that there are try without catch, but it seems to be getting confused about the location. https://github.com/IGJoshua/farolero/blob/master/src/cljc/farolero/core.cljc#L82-L88 🧵
#2022-01-2722:00Joshua SuskaloSo it's intentional that there's a try without a catch here, specifically because the intention here is that I want to prevent a recur to the function there.#2022-01-2722:01Joshua SuskaloI'm perfectly fine with kondo emitting a warning, but it's not specifying a source location, and I'm confused why.#2022-01-2722:01borkdudemakes sense. you can stick a #_:clj-kondo/ignore for that case#2022-01-2722:01Joshua SuskaloMaybe it's a bug that it's not got the source location?#2022-01-2722:01borkdudeI'm not sure. Are you using a hook to lint this code? Then there might not be a location attached to the node#2022-01-2722:02Joshua SuskaloOh, yeah, that's probably true because it's one of the constructed nodes that's added to the code.#2022-01-2722:03Joshua SuskaloSo how could I fix this, do I need to emit a comment node or something to tell kondo not to lint my macro with this linter?#2022-01-2722:04borkdudeyou could just remove the try perhaps and make it a do or so#2022-01-2722:04Joshua SuskaloRight, but then kondo wouldn't complain about recur there#2022-01-2722:05Joshua Suskaloand that's why the try was put in there in the first place#2022-01-2722:05Joshua SuskaloI think I could just emit an empty finally block#2022-01-2722:05Joshua Suskalothat might work#2022-01-2722:06borkdudeclever#2022-01-2722:07Joshua SuskaloThat worked. Glad it's not a bug.#2022-01-2722:08Joshua SuskaloThanks again for kondo, I love it!#2022-01-2722:08borkdudeThank you :)#2022-01-2722:08borkdudePerhaps clj-kondo should not emit warnings without a location#2022-01-2722:08borkdudebut on the other hand, you do catch some issues like this, if it does#2022-01-2722:09Joshua Suskaloyeah, so far every time it's emitted a warning without a location it's been something that told me something was up with my hooks, so I think they're useful.#2022-01-2822:53Stefan TI know there are many existing topic related to custom macros, but I’m having a hard time finding a solution to this specific problem. As we know, the defrecord macro generates some constructor functions like -> and map->. Suppose I have a custom macro like defrecord+ which generates custom constructor functions. What are my options for configuring clj-kondo to handle this? Ideally I’d like to avoid having to add a configuration entry for every custom record definition created through my defrecord+.
(defrecord+ MyRecord [id data])

; unresolved var
(make->MyRecord {:id 1 :data "something"})
#2022-01-2822:55borkdude@UQE9SS4DP
{:lint-as {your.ns/defrecord+ clojure.core/defrecord}}
#2022-01-2822:57Stefan TIn this example, is your.ns the namespace that defines the defrecord+ macro or the namespace that is using it?#2022-01-2822:59borkdudedefining#2022-01-2823:00Stefan TI currently have this in my configuration under :lint-as as suggested, but that doesn’t seem to work.#2022-01-2823:01Stefan T
(ns my-ns
  (:require [my-custom-record :refer [defrecord+]]))

; No lint issues here
(defrecord+ MyRecord [id data])

(ns my-other-ns
  (:require [my-ns :as mns]))

; unresolved var
(mns/make->MyRecord {:id id :data data})
#2022-01-2823:01borkdudeCan you show your entire config? Make sure you put :lint-ason the top level#2022-01-2823:02Stefan TYeah just to be clear, I’m not getting lint issues on the usage of defrecord+ its from the custom function it generates.#2022-01-2823:02borkdudemake->MyRecordis not defined by defrecord, that is map->MyRecord#2022-01-2823:03Stefan TThat’s what I’m saying, defrecord+ defines non-standard constructor functions#2022-01-2823:03borkdudeah ok. your option here is to write a custom config macro or hook. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2022-01-2823:04borkdudeSomething which just expands into
(do (declare make->MyRecord) (defrecord MyRecord [] ...)
or so will do
#2022-01-2823:05Stefan TAh ok, so I can set the :analyze-call for the defrecord+ macro, and I won’t need to configure :analyze-call for each of the make->X functions?#2022-01-2823:05borkdudeindeed#2022-01-2823:05Stefan TExcellent. That clears things up. Thanks!#2022-01-2823:06borkdudethere is :analyze-call but also :macroexpandwhich will probably be easier to start with, you can just provide a normal macro there, but it gives less precise warnings / locations#2022-01-2823:07Stefan TGotcha, I’ll give it a try.#2022-01-2823:46Stefan TThis question might be specific to clojure lsp or vscode, but can you recommend a good workflow for developing and testing these hooks?#2022-01-3115:15borkdudeCurrently, use clj-kondo on the command line and insert printlns in the code for debugging, and then run it on examples#2022-02-0823:50Stefan TYeah I had to smack myself when I realized I was working the really really hard way 🙂 using the command line was the way to go here! Hooks are working quite well for me now, thank you!#2022-02-0823:54Stefan TThough I ran into this issue that puzzled me. I thought it would be a no brainer to use :lint-as but that was not working, I had to use a custom hook which seems like it would do the same thing. Any idea here?
(ns shared-lib.io.utils)
(defmacro with-tmp-file* [[sym f] & body] ...)

;; Usage like:
(io-utils/with-tmp-file* [tmp-file "asset"] ...)
Tried adding :lint-as
{:lint-as {shared-lib.io.utils/with-tmp-file* cojure.core/let}}
Did not work. The hook works though:
(defn with-tmp-file* [{:keys [node]}]
  (let [new-node (api/list-node
                   (list* (api/token-node 'let)
                          (rest (:children node))))]
    {:node new-node}))
#2022-02-0908:37borkdude@UQE9SS4DP a typo: cojure.core/let#2022-02-0908:37borkdudeshould be clojure.core/let#2022-02-0918:47Stefan T😢 I need to catch up on sleep#2022-02-0918:47Stefan T:rolling_on_the_floor_laughing: thanks#2022-01-3115:06neil-dwI'm using clj-kondo 2022.01.15 (with the latest Calva version), and it's treating clojure.core/alias as undefined. Is that a known issue? [Update: not a Kondo issue, I just didn't understand the behavior I should expect in a .cljc file. Thanks @borkdude!]#2022-01-3115:07borkdude@U02STT6CVK5 Need more info. Can't repro using a simple example locally here.#2022-01-3115:08borkdudeAre you in a .cljc file?#2022-01-3115:13neil-dw@borkdude: I was, actually. I get the same result in a .cljs file. But I see that trying it in a .clj file works.#2022-01-3115:14borkdudeYes, the issue is that alias is not defined in ClojureScript. So in a .cljc branch you'll have to put that code in a reader conditional.#2022-01-3115:15neil-dwAh, that makes sense! Thank you!#2022-01-3115:29lreadThis open issue is related: https://github.com/clj-kondo/clj-kondo/issues/1196, maybe someday I’ll find time to work on it! simple_smile#2022-01-3115:30borkdudeFeel free to upvote the issue for higher priority. :)#2022-01-3119:14Noah BogartIs it possible to have a linter check if a given required namespace exists and warn if it doesn’t?#2022-01-3119:15borkdude@nbtheduke That isn't yet available. Could be done though.#2022-01-3119:16borkdudeThere is one caveat: clj-kondo works and has always worked with partially linted projects#2022-01-3119:16Noah Bogartwant me to open a new github issue about it? i see https://github.com/clj-kondo/clj-kondo/issues/842 and https://github.com/clj-kondo/clj-kondo/issues/1240 and https://github.com/clj-kondo/clj-kondo/issues/1460 are all about namespaces and filenames#2022-01-3119:16Noah Bogartwhat do you mean by “partially linted projects”?#2022-01-3119:16borkdudeThat you're not required to lint your project + deps to have good feedback or false positives due to not doing that#2022-01-3119:18borkdudeSo if there is a namespace not available in the cache, then clj-kondo just assumes you haven't linted that one yet, it can't see the difference between: it doesn't exist or it might exist maybe in the future, but I haven't seen it yet#2022-01-3119:19borkdudePerhaps it's better if clojure-lsp did this linter, because clojure-lsp does require you to index the whole project. Similar to why :clojure-lsp/unused-public-var is implemented by lsp and not by clj-kondo out of the box#2022-01-3119:20borkdudeOr clj-kondo should have something in its cache that signals that clj-kondo --lint $classpath --dependencies has linted the entire project#2022-01-3119:20borkdudeand then it could with more certainty say: this ns doesn't exist#2022-01-3119:21borkdudeMaybe we could write such a file when you lint using --dependencies and after that activate this project-wide linter#2022-01-3119:23borkdudeThere is one more edge case I could come up with, is when you rename namespaces, then clj-kondo might still think the old name still exists since there's that file lingering in the cache#2022-01-3119:24borkdudebut that might be better than nothing#2022-01-3119:25borkdudeok, let's do it. I'll make an issue about it#2022-01-3119:29borkdude@nbtheduke https://github.com/clj-kondo/clj-kondo/issues/1564#2022-01-3119:31Noah BogartIt’s interesting how the classpath makes this more challenging than, say, a node project where it’s as “simple” as searching first the local files and then node_modules for a given filepath#2022-01-3119:32borkdudewell, when you've linted your entire project, the linter is easy. it's just that you shouldn't emit warnings when you haven't.#2022-01-3119:32borkdudeclj-kondo has a file for each namespace in its cache#2022-01-3119:32borkdudealso partitioned by clj, cljs and cljc#2022-01-3119:34borkdudeWhen you lint a file, like (ns foo (:require [clojure.set])) then clj-kondo will read the file .cache/v1/clj/clojure/set.transit.json into memory#2022-01-3119:34borkdudeso when there is (:require [clojure.setx]) (typo), there should be no file and then it's a warning#2022-01-3119:37Noah Bogarthuh yeah, that makes sense#2022-01-3119:38Noah Bogartso it’s a… two step process? or multi-step at least. first pass is “add a file to the cache for each file in the class path”, and then the second pass allows for referencing and filling those files?#2022-01-3119:38borkdudeevery time clj-kondo lints a file, it writes the result of analyzing that file to the cache#2022-01-3119:39borkdudeso if you start with an empty cache and just start editing your project, the linting gets increasingly more informed.#2022-01-3119:39Noah Bogartwhich is why it doesn’t attempt to do this kind of linting yet, if you lint a single file it won’t have any other files available in the cache. okay, that makes more sense#2022-01-3119:39borkdudeyes#2022-01-3119:40Noah Bogartthanks for explaining#2022-02-0114:54Nom Nom MousseWow!#2022-02-0114:54Nom Nom MousseTypechecks!#2022-02-0116:11winsomeI've got (set! *warn-on-reflection* true) in a namespace, but clj-kondo is flagging it as an unresolved symbol. When I play with the playground tool, it doesn't have any problem with it, how can I correct my setup?#2022-02-0116:13borkdude@winsome is this in a .cljc file? then this is because CLJS doesn't have that and you should put it behind a reader conditional#2022-02-0116:14winsomeyup, bingo. Thanks 🙏#2022-02-0116:41lread@winsome, consider, if you wish, voting with a 👍 on https://github.com/clj-kondo/clj-kondo/issues/1196 to make these types of errors clearer.#2022-02-0117:46danielcomptonI'm running clj-kondo as clj-kondo --parallel --lint src --config .clj-kondo/config-ci.edn but am not seeing CPU go over 100% (a single core), even on a M1X MacBook Pro. Is this expected? I wasn't quite sure what the granularity of parallelism is#2022-02-0118:09borkdude@danielcompton sources are grouped per .jar and per source dir, so linting only one dir will happen only on one core#2022-02-0119:44danielcomptonAh, 😞#2022-02-0120:48borkdude@danielcompton is linting your src too slow?#2022-02-0120:51borkdudeyou could split the src dir into --lint src/dir1:src/dir2 too speed it up :)#2022-02-0123:47danielcomptonYeah, I split it into the 37 next level directories but it only sped it up from 10s to 7s and it only get to about 250% CPU, where it could get up to 800-1000%#2022-02-0123:48danielcomptonNot sure how much the Rosetta translation from Intel to ARM is costing#2022-02-0206:55borkdudeIs this on Whimsical and is that open source?#2022-02-0403:10danielcomptonIt is on Whimsical, unfortunately not open source 🙂#2022-02-0407:57borkdudeYou can always hire me for a couple of non-OSS hours to improve your kondo setup ;-). I've been doing this for several other companies #2022-02-0119:53lreadDo you have a core issue with clj-kondo @danielcompton? :drum_with_drumsticks:#2022-02-0411:41mknoszligre https://github.com/clj-kondo/clj-kondo/issues/1560 i’m still wondering about that switch to control the warning on private tasks. given
{:tasks
 {-a {:doc "private"}
  b {:doc "public"
     :depends [-a]}}}
bb tasks gives
> bb tasks
The following tasks are available:

b public
personally, my main reason for having clj-kondo remind me to provide doc strings is so task info will be available on the shell… :doc being used by babashka for private tasks in any way?
#2022-02-0411:47borkdudenot really no#2022-02-0411:47borkdudegood point#2022-02-0411:48borkdudemaybe default to no warning on private tasks then (and leave it at that for the first iteration)#2022-02-0412:02borkdude@maximilian I think a nice addition could be to actually get linting in the task code.#2022-02-0412:03mknoszligoh, that’s a nice one#2022-02-0412:03borkdudeThe way this can be done is to wrap the task code as a function with :depends as the arguments#2022-02-0412:03borkdudeso {:task (+ a b c) :depends [a b c]} becomes (fn [a b c] (+ a b c)) and then lint that function#2022-02-0412:04borkdudebut this will cause unused function argument warnings... could also expand as (declare a b c) (+ a b c)#2022-02-0412:04mknoszligwill probably have to account for :requires as well#2022-02-0412:04borkdudethat's closer to how it works in the tasks impl anyways. yes#2022-02-0412:05borkdudewe can talk in #clj-kondo-dev about this as to not disturb anyone else with details about this#2022-02-0412:06mknoszligTIL 😅#2022-02-0417:43porksausagescan kondo be configured to not lint library code? e.g:#2022-02-0418:31borkdudeWhat editor is this? I need more context than a screenshot.#2022-02-0418:32borkdudeclj-kondo only lints what you provide to it, so it depends on whatever tool calls clj-kondo#2022-02-0418:46porksausagesit's vscode + calva, and its really strange because it doesn't happen when first loading up a project#2022-02-0418:47porksausagesit only happens after being open for 1-2 hours#2022-02-0418:48porksausagesand then after restarting, it's fine for another hour or two#2022-02-0418:49borkdudeAre you copying .jar files into your project somehow?#2022-02-0418:51porksausagesno it's just a project generated with lein new app [name] , zero changes to the structure of the project - not even a new file#2022-02-0418:52borkdudeI'm not sure why this happens. Have you also tried in #calva or #lsp?#2022-02-0418:55borkdude\cc @UKFSJSM38 @U0ETXRFEW#2022-02-0418:56ericdalloI think this happens indeed, when you open a external dependency the editor loads the content and add the file as a LSP workspace fie, to most navigation and other features work#2022-02-0418:57ericdalloone of the drawbacks are the lint error#2022-02-0418:57ericdalloI already faced this with multiple lsps, not only clojure, not sure how we could fix it#2022-02-0418:57ericdallomaybe don't return diagnostics when the file is external, but the issue is how we know a file is external, need some POC#2022-02-0419:07porksausagesyeah i asked in #calva and pez recommended asking here, so i'm not really sure where the problem lies. i'm definitely not adding any external dependencies, i don't even know how to do that yet, but i'm not sure if leiningen or calva are adding a dependency or something.#2022-02-0419:08borkdudeAre you opening core.clj from clojure itself?#2022-02-0419:08ericdalloexternal dependencies == opening a file not from your project like clojure.core, clojure.string etc#2022-02-0419:08porksausagesi'm not opening core.clj at all as far as i know?#2022-02-0419:09borkdudeI'm out of clues, sorry, clj-kondo is a pretty simple tool: it lints what you tell it to.#2022-02-0419:09ericdalloyeah, for sure it's not a kondo issue#2022-02-0419:10ericdallobut not sure it's a calva o lsp one, it's kind of expected this behavior#2022-02-0419:10porksausagesi don't know clojure at all i'm in the process of trying to learn so i probably can't help as much as i'd like to but here's exactly what i've done: 1. i generated a new project with lein new app clojure-noob 2. i opened the directory it created in vscode 3. i opened a repl 4. the error shows up an hour or two later#2022-02-0419:11porksausagesit makes sense if it's not a kondo issue but i don't see how this could possibly be expected behaviour?#2022-02-0419:12porksausagesunless i'm misunderstanding what that means lol#2022-02-0419:13porksausagesbut thank you for your help either way#2022-02-0419:13ericdallofor sure it's not expected if you didn't open a file, but I think you did at some point#2022-02-0419:15porksausageshang on i'm being dumb here, i've only just realised that core.clj is the "main" file so yeah i am opening it#2022-02-0419:16porksausagesthats the file i'm working in#2022-02-0419:16porksausagesbut these errors and warnings are not corresponding to anything inside the actual file#2022-02-0419:16ericdalloare you sure? core.clj from your project and core.clj from clojure.core are different file. from your print it seems you opened clojure.core, maybe finding a definition of some function or something#2022-02-0419:17porksausagesthis is the only file i've ever opened since starting to learn clojure in this project:#2022-02-0419:18porksausageshowever you make a good point, maybe this is happening when i hover my mouse over a function and it shows the doc?#2022-02-0419:18ericdalloit should not, we only lint when we open the file or itś a project file when starting lsp#2022-02-0419:20porksausagesweird. well, until i figure out exactly what action is making this happen this is probably just wasting your time so i'll just keep an eye on it for now until i figure it out#2022-02-0419:20porksausagesthank you for your help#2022-02-0419:22ericdallono problem, feel free to start with a issue on Calva, the entrypoint, where we can debug and find the root cause#2022-02-0503:36pinkfrogI was just about to ask the same question in this channel.#2022-02-0503:36pinkfrogBecause of go to definitions and stuff like that, I often open the clojure.core file, and this brings a lot of clj kondo issues:#2022-02-0503:37pinkfrogPossible to exclude the .m2/ files from linting?#2022-02-0922:58agoldI'm having the same problem, but it only started a few days ago, possibly after latest Calva update. The errors are coming from clojure.core, which shouldn't be linted, as I haven't opened. They can be triggered by random changes in my code: deletion of a line, beginning a new form, etc. I have been using Calva for quite a while and first encountered this only a few days ago.#2022-02-0923:05ericdallothis probably started to happen after we fixed on clojure-lsp the find definition of a jar, I think we can not return lint for jar dependencies, I'll do the proper changes on clojure-lsp side#2022-02-1000:49ericdallo@U2CR1J4UV @UGC0NEP4Y @UH1SWK753 I just made a https://github.com/clojure-lsp/clojure-lsp/commit/4ef029d85d05bb4be435cdeb38fa538d33eadbecstopping linting external files which solve this issue, it should be available on next clojure-lsp release, if you wanna test it locally, you can clone the repo and run make to generate a local clojure-lsp#2022-02-0513:56borkdudeWork in progress: :redundant-fn-wrapper https://twitter.com/borkdude/status/1489960857744416771#2022-02-0710:14oxalorg (Mitesh)Hello! Thanks for all the awesome work on clj-kondo. I'm using it to get some analysis on my code base and then use rewrite-clj to modify it. So for example I want to get all the uses of a function called split lets say, so most of the normal analysis works. i.e. it finds the right usages of the function call and ignores the local scoped versions. But these quoted forms do not appear in :var-usages of the analysis, neither can I get clj-kondo to lint them:
(defn quoted-split []
  ;; does not work
  '(split "qu zu mu" #" "))

(eval (quoted-split))

;; does not work
((eval 'split) "qu zu mu" #" ")

(defmacro split-wrap [& body]
  ;; works 
  `(split 
Anyone has an idea if this is something which is supported by clj-kondo? Thanks!!! 🌸
#2022-02-0710:16borkdude@mitesh quoted forms are just data, and that data doesn't necessarily use vars. It's impossible for clj-kondo to guess that this data will be used to refer to vars. In general, try to avoid eval .#2022-02-0710:17oxalorg (Mitesh)Yup that's what I thought. It makes complete sense to not try and lint/change quoted stuff as that is dangerous territory and we never really know what the user is doing.#2022-02-0710:18oxalorg (Mitesh)Thanks for confirming this 🙌#2022-02-0710:18borkdudeIf you write macros like:
(defmacro foo [] `(do ~split ...))
in that case clj-kondo will see the usage of split.
#2022-02-0710:19oxalorg (Mitesh)Perfect thanks!#2022-02-0711:47borkdudeBtw, clj-kondo also has the ability to run macros via hooks, but you need to configure those#2022-02-0810:40donavanAm I correct in assuming that :unsorted-required-namespaces checks ordering of splicing reader conditionals as if they were already spliced. I guess that makes sense...#2022-02-0810:42donavanIs there a way to currently support having one splicing conditional at the end of the require block and have each part of it sorted? E.g.:
(ns some.ns
  (:require
   [com.fulcrologic.fulcro.components :as comp :refer [defsc]]
   #
#2022-02-0810:43donavanThat currently fails the linter because (I think) after splicing it would be out of order#2022-02-0810:50borkdudeI'm not sure, it might just ignore these special cases to not cause false positives#2022-02-0810:55donavanIt currently raises warnings for us on clj-kondo v2022.01.15 . I wanted to post the above as an arg to the clj-kondo command but I get an error saying it’s an unparsable ns form (I think because there is no file?)#2022-02-0810:56borkdudeyou can lint from stdin using --lint -#2022-02-0811:31donavanThe unparsable ns form error occurs even if there is a file. This is what I get…
clj-kondo-repro on  main [?]
❯ clj-kondo --lint src
src/myname/myapp.clj:0:0: error: Can't parse src/myname/myapp.clj, Unparsable namespace form
linting took 166ms, errors: 1, warnings: 0
…in this repro https://github.com/dcostaras/clj-kondo-repro
#2022-02-0811:34borkdudeyou cannot use reader conditionals in .clj files#2022-02-0811:34donavanoof, sorry!#2022-02-0811:34borkdudemaybe clj-kondo should warn about this :)#2022-02-0811:34borkdudethere might already be an issue about this, but if not, feel free to make one#2022-02-0811:35borkdude(about reader conditionals in .clj)#2022-02-0811:39donavanWill do, weirdly enough I could jack-in and execute forms!#2022-02-0811:39borkdudethe REPL might accept it#2022-02-0811:40borkdude
$ clj
Clojure 1.11.0-alpha3
user=> #?(:clj 1)
1
#2022-02-0812:41donavanThere was an issue about reader conditionals awhile back https://github.com/clj-kondo/clj-kondo/issues/80 it could be reopened?#2022-02-0812:42borkdudere-opened#2022-02-0812:42borkdudethanks for finding that#2022-02-0812:43donavanI’ve updated the repro project https://github.com/dcostaras/clj-kondo-repro The behaviour is now:
❯ clj-kondo --lint src
src/myname/myapp.cljc:5:16: warning: Unsorted namespace: com.fulcrologic.fulcro.dom
src/myname/myapp.cljc:6:15: warning: Unsorted namespace: com.fulcrologic.fulcro.dom-server
linting took 215ms, errors: 0, warnings: 2
Could this be configured to not warn in that case… or ideally check the sorting of the parts?
#2022-02-0812:48borkdude@U0VP19K6K if you write:
(ns myname.myapp
  (:require
   [com.fulcrologic.fulcro.components :refer [defsc]]
   [taoensso.timbre :as timbre]
   #?(:clj [com.fulcrologic.fulcro.dom-server :as dom])
   #?(:cljs [com.fulcrologic.fulcro.dom :as dom])))
then the order doesn't matter, but somehow in the splice that's not been accounted for yet, it seems. we should just fix that to not warn
#2022-02-0812:48borkdudeissue welcome. for now you can use a non-splice perhaps#2022-02-0812:50donavanthanks, I’ll open the issue. We’re attempting to turn it on in an existing project so probably wont change all NSs just yet! Thanks borkdude#2022-02-0812:59donavanhttps://github.com/clj-kondo/clj-kondo/issues/1571#2022-02-0812:55imreIs there an established good approach to testing my custom hooks in my library?#2022-02-0812:56borkdude@imre testing while developing or testing as in QA?#2022-02-0812:57imreWell, both. For developer feedback I used lots of (prn (api/sexpr node)) as suggested at https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2022-02-0812:57imreThis is less than ideal but it worked for now#2022-02-0812:58imreI haven't had time to figure out a cleaner way#2022-02-0812:58borkdudeFor testing as in QA I would just lint your sources and make sure your macros are used in such a way that should be covered by the linting#2022-02-0812:58imreBut it would be nice to be able to persist a few tests so I don't break the hook later on#2022-02-0812:58borkdudeand then put that linting in a test or CI job#2022-02-0812:59borkdudeAs for dev, I'm thinking of improving that#2022-02-0812:59imreThat works to some extent but I also want to write tests that would fail the linter for specific reasons#2022-02-0812:59borkdudedo you mean, you do validation in the linter and would like to test for that?#2022-02-0812:59imreyes#2022-02-0813:00borkdudeYou can test for the linter output?#2022-02-0813:00borkdudeyou can use clj-kondo as a JVM library and make assertions on the findings#2022-02-0813:01borkdude
(:findings (clj-kondo.core/run! {:lint ["input-file.clj"]}))
#2022-02-0813:01imreooh, that would work I guess!#2022-02-0813:01imrelet me have a go at it#2022-02-0813:09imreIs there a way to pass file contents in there as a string?#2022-02-0813:11borkdudeyou can lint from stdin like this:
(with-in-str "(+ 1 2 3)" (run! {:lint ["-"]}))
#2022-02-0813:11imrePerfect, thank you very much#2022-02-0814:20imrehttps://github.com/fulcrologic/guardrails/pull/30 in case you're interested what I needed this for. Thanks again for the help!#2022-02-0820:23imreOne more question regarding the dev workflow: using the JVM method you shared above, how can I reload the hook code I'm testing after I make changes without having to restart my repl?#2022-02-0820:54imretest uses the project's .clj-kondo/config which references another config which sets up the hook via analyze-call#2022-02-0820:59borkdude@imre Ah yeah#2022-02-0821:00borkdudeI think (require '[clj-kondo.impl.hooks] :reload) will work#2022-02-0821:01imreAnd indeed it does! Thank you very much again!#2022-02-0915:49borkdudeIf you want clj-kondo to find "redundant fn wrappers" please take this for a spin!
clojure -Sdeps '{:deps {clj-kondo/clj-kondo {:git/url "" :git/sha "2cc9777752d9f54ed91baa4c6ddaa0c2b8812049"}}}' -M -m clj-kondo.main --config "^:replace {:linters {:redundant-fn-wrapper {:level :warning}}}" --lint src
and 🙏 report any false positives as a reply to this message.
#2022-02-0917:42wilkerluciois this a false positive?
(defn sub-sequence? [seq-a seq-b]
  (->> (map #(= % %2) seq-a seq-b)
       (every? true?)))
#2022-02-0917:44wilkerlucio(Im guessing its not, I can replace #(= % %2) with =, is this what this linter is looking for?)#2022-02-0917:51borkdudeyes#2022-02-0915:52dpsuttoncan you paste an inline config that uses only that linter? Quite interested to run it but will get lots of other output at the moment (i think)#2022-02-0915:52dpsuttonsomething like "^:replace {:linters {??}}"#2022-02-0915:53borkdudeyes, exactly that#2022-02-0915:53borkdudeor maybe {:linters ^:replace {}}#2022-02-0915:53borkdudenot sure anymore :)#2022-02-0915:53dpsutton"--config ^:replace {:linters {:redundant-fn-wrappers :warning}}" i guess?#2022-02-0915:54borkdudeis this bash?#2022-02-0915:54borkdudeyou must then spit --config out of the string#2022-02-0915:54borkdude
--config "..."
#2022-02-0915:55dpsuttonzsh but yeah#2022-02-0915:58dpsuttoni threw
(defn foo [x]
  (let [inc' #(inc %)]
    (inc' x)))
in a file i’m working on and
clojure -Sdeps '{:deps {clj-kondo/clj-kondo {:git/url "" :git/sha "2cc9777752d9f54ed91baa4c6ddaa0c2b8812049"}}}' -M -m clj-kondo.main --config "^:replace {:linters {:redundant-fn-wrapper :warning}}" --lint src
and got no warning
#2022-02-0915:58borkdude
--config "^:replace {:linters {:redundant-fn-wrapper {:level :warning}}}"
worked for me locally here
#2022-02-0915:58borkdudehmm I'll try that example#2022-02-0915:59borkdudeWorks here#2022-02-0916:00borkdudehmm, with the version I previously compiled, but maybe not with the branch. taking a closer look#2022-02-0916:01borkdudeit also works for me when I remove that config, there must be something wrong with that part#2022-02-0916:02borkdudethis is with my compiled version (which is slightly behind on the branch)#2022-02-0916:03borkdudeThis worked:
$ clojure -Sdeps '{:deps {clj-kondo/clj-kondo {:git/url "" :git/sha "2cc9777752d9f54ed91baa4c6ddaa0c2b8812049"}}}' -M -m clj-kondo.main --config "^:replace {:linters {:redundant-fn-wrapper {:level :warning}}}" --lint /tmp/dude.clj
#2022-02-0916:04dpsuttonah, it needs a map with {:level :warning}#2022-02-0916:04borkdudeah yes#2022-02-0916:05dpsuttonsuccess! #(vector? %) ha#2022-02-0916:05dpsuttonoh nice, it caught a multi-arity map version#2022-02-0916:06borkdude?#2022-02-0916:06borkdudecan you show?#2022-02-0916:06dpsutton
(map (fn [join rhs]
       (rhso join rhs))
     joins rhses)
is of course (map rhso joins rhses)
#2022-02-0916:06borkdudeah :)#2022-02-0916:06dpsuttonthe single arity versions are easy to see. i didn’t notice this one right away#2022-02-0916:06dpsuttonnice job#2022-02-0916:08dpsuttonyou should ping ghadi about this#2022-02-0916:08borkdudeyeah, I've done that#2022-02-0916:08borkdudehe found one in nubank's code#2022-02-0916:16borkdudeI think I'll disable this linter by default, what do you think?#2022-02-0916:18borkdudeFor some reason I write #(genysm) a lot#2022-02-0916:32dpsuttonha#2022-02-0916:32dpsuttonmakes me think of some core set of default enabled linters, and an easy way to enable all new linters that haven’t made their way into core yet?#2022-02-0916:32dpsuttonbut yeah i agree maybe not by default. but i wonder how many people use non-default linters#2022-02-0916:33borkduderight, the original cause for this linter was that beginners tend to write (update foo :bar #(inc %))#2022-02-0916:34borkdudeand those beginners might not enable a non-default linter#2022-02-0916:34borkdudeMaybe I can make it opt-in for 1 quarter and then enable it by default#2022-02-0916:35borkdudeto get rid of initial false positives#2022-02-0920:47borkdudeclj-kondo, a linter for clojure (code) that sparks joy, v2022.02.09 clj-kondo 2022.02.09. • Feature https://github.com/clj-kondo/clj-kondo/issues/1549: detect and warn on cyclic task dependencies in bb.edn (https://github.com/mknoszlig) • Feature https://github.com/clj-kondo/clj-kondo/issues/1547: catch tasks undefined tasks present in `:depends`. (https://github.com/mknoszlig) • Feature https://github.com/clj-kondo/clj-kondo/issues/783: `:keys` can be used in `:ret` position, also fixes types return map call as input for another typed map function. (https://github.com/pfeodrippe) • Feature https://github.com/clj-kondo/clj-kondo/issues/1526: detect redundant fn wrappers, like `#(inc %)`. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#redundant-fn-wrapper. This linter is :off by default, but may be enabled by default in future versions after more testing. • Feature https://github.com/clj-kondo/clj-kondo/issues/1560: lint task definition keys in bb.edn (https://github.com/mknoszlig) • Feature https://github.com/clj-kondo/clj-kondo/issues/1484: Add analysis information about protocol implementations. (https://github.com/ericdallo) • Fix https://github.com/clj-kondo/clj-kondo/issues/1563: vector inside list should not be linted as function call when inside tagged literal. • Fix https://github.com/clj-kondo/clj-kondo/issues/1540: imported class flagged as unused when it only appears in annotation metadata. • Fix https://github.com/clj-kondo/clj-kondo/issues/1571: ignore spliced reader conditionals wrt. namespace sorting. • Fix https://github.com/clj-kondo/clj-kondo/issues/1574: def usage context contains reference of the re-frame reg-sub it is used in. (https://github.com/benedekfazekas)#2022-02-0922:05lreadhttps://github.com/clj-commons/rewrite-clj/commit/d9eda955f09d09fd1246244ce9d8a4ec5b247ea8!#2022-02-0922:10borkdudeFor people not noticing that @lee posted a link to a commit where he applied :redundant-fn-wrapper , he did. @ericdallo Perhaps clojure-lsp could also automatically clean this :)#2022-02-0922:31lreadNot as dramatic as my “coolio” above, but still awesome!: https://github.com/lread/test-doc-blocks/commit/9518b27c0cdeca88e5cebce9d1abe706c12ca869.#2022-02-0923:05lreadFor the curious, https://github.com/cljdoc/cljdoc/commit/abb606f8229feec8b3b83a4bc94fc119aa542aaf.#2022-02-0923:07ericdallo@borkdude we can for sure create a code action on clojure-lsp to auto remove that when that lint exists on the line :)#2022-02-0923:20ericdalloWhat do you think about a linter :simplify-not-equal which check if you typed (not (= :foo :bar)) suggesting to replace with (not= :foo :bar) ?#2022-02-0923:23borkdudethere's been a previous attempt to this but it wasn't so clear cut that one form is always desirable over another#2022-02-0923:23ericdallomakes sense#2022-02-0923:32Darin Douglass(not (= …)) all the way :)#2022-02-1013:01olyTried looking for this is there an easy way to run clj-kondo on a polylith project perhaps doing a glob or something so i can match any file under a /src/ folder or something#2022-02-1013:02borkdude@oliver.marks you can use clojure -Spath to get a classpath in your project and then you could filter out directories that fall within the project maybe?#2022-02-1013:02borkdudeusing a babashka script or otherwise#2022-02-1013:03borkdudee.g.:
$ clojure -Spath | bb -e '(->> (str/split (str/trim (slurp *in*)) #":") (filter fs/directory?))'
("src" "shared/src" "resources" "java/target/classes" "/Users/borkdude/Dropbox/dev/clojure/metabase/java/target/classes")
#2022-02-1013:04olyokay I was kind of hoping for a more built in so I can use it in my github action, and not have to add a list of folders#2022-02-1013:05borkdudeclj-kondo is agnostic of build tooling, it has nothing built in regarding deps.edn, polylith, lein or whatever. just give it the paths to lint and it will lint. You could also just do clj-kondo --lint .#2022-02-1013:05oly
- name: Code Linting
        uses: DeLaGuardo/
This is the current step in the action
#2022-02-1013:06olyI guess to do the above i would need a different action to get the list and pass to clj-kondo#2022-02-1013:06borkdudeAre your sources in workspace?#2022-02-1013:06borkdudethen that should be sufficient#2022-02-1013:07olyyeah that picks up output in resources folders so I get files like this linted
ublic/cljs-out/dev/reagent/impl/template.cljs
#2022-02-1013:08olyI am guessing clj-kondo does not work with .gitignore ?#2022-02-1013:08borkdudeand you want to avoid this?#2022-02-1013:09olythe above I am getting locally by the way they are not in the repo on github but its more an example#2022-02-1013:09borkdudeyou can do --config "{:output {:exclude-files ["resources"]}}"#2022-02-1013:09olywell reagent is an external library#2022-02-1013:09olywill that ignore them even if they are under sub directories
#2022-02-1013:10borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#include-and-exclude-files-from-the-output#2022-02-1013:10borkdudeit's a regex#2022-02-1013:10olyoh right that will work then awesome 🙂#2022-02-1013:13oly
Unexpected error. Please report an issue.
java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to java.lang.String
	at clojure.core$re_pattern.invokeStatic(core.clj:4834)
	at clj_kondo.impl.core$filter_findings$iter__16030__16034$fn__16035$fn__16036$fn__16039.invoke(core.clj:524)
	at clojure.core$some.invokeStatic(core.clj:2705)
	at clojure.core$some.invoke(core.clj:2696)
	at clojure.core$comp$fn__5826.invoke(core.clj:2574)
	at clj_kondo.impl.core$filter_findings$iter__16030__16034$fn__16035$fn__16036.invoke(core.clj:524)
	at clj_kondo.impl.core$filter_findings$iter__16030__16034$fn__16035.invoke(core.clj:511)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:51)
	at clojure.lang.RT.seq(RT.java:535)
	at clojure.core$seq__5420.invokeStatic(core.clj:139)
	at clojure.core$sort.invokeStatic(core.clj:3101)
	at clojure.core$sort_by.invokeStatic(core.clj:3107)
	at clojure.core$sort_by.invokeStatic(core.clj:3107)
	at clj_kondo.core$run_BANG_.invokeStatic(core.clj:181)
	at clj_kondo.main$main.invokeStatic(main.clj:130)
	at clj_kondo.main$main.doInvoke(main.clj:126)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:667)
	at clj_kondo.main$_main$fn__16234.invoke(main.clj:177)
	at clj_kondo.main$_main.invokeStatic(main.clj:177)
	at clj_kondo.main$_main.doInvoke(main.clj:175)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clj_kondo.main.main(Unknown Source)
hum that causes an exception 😞
#2022-02-1013:13borkdudewhat do you have in your config#2022-02-1013:13borkdudeprobably a syntax mistake#2022-02-1013:15olyah thanks for the help copied your example exactly needed to escape the " 🙂#2022-02-1021:02tomdI've noticed foo in the following example is an "unused binding" lint warning:
(let [foo "2022-02-10"
      bar #time/date foo]
  bar)
is this a bug or expected behaviour?
#2022-02-1021:06borkdude@tomd a bug. issue welcome#2022-02-1021:06tomdgreat thanks - on it's way...#2022-02-1106:30alexHi there, do you have any tips for circumventing an "Unresolved namespace" error when invoking macros on fully qualified symbols? I have a lazy-component macro that takes a fully qualified symbol for lazily loading modules in cljs. At all of the call-sites, I get an unresolved namespace error due to not requireing the namespace (this is purposeful so that we don't load those namespaces until necessary)
(defmacro lazy-component
  [the-sym]
  `(components.lazy/lazy-component* (shadow.lazy/loadable ~the-sym)))

;; call-site
;; my-app.components.huge-component is not included in the namespace declaration

(lazy/lazy-component components.huge-component-to-be-rendered-async)
#2022-02-1111:52borkdudeWhy doesn't
components.huge-component-to-be-rendered-async
contain a var name?
#2022-02-1114:50alexThanks for pointing that out. I transcribed a poor example. Should say (lazy/lazy-component components.huge-component-to-be-rendered-async/the-component)#2022-02-1114:52alexand the corresponding clj-kondo warning is
[unresolved-namespace] Unresolved namespace components.huge-component-to-be-rendered-async. Are you missing a require?
#2022-02-1114:53borkdudeand lazy-component is something like requiring-resolve?#2022-02-1114:54borkdudedo you use this call on the top level in your namespace?#2022-02-1114:57borkdudeyou can add components.huge-component-to-be-rendered-async to the :exclude-ed namespace of the unresolved namespace linter perhaps, or try this (experimental):
:config-in-call {your-ns/lazy-component {:linters {:unresolved-namespace {:level :off}}}}
#2022-02-1115:05alex> and lazy-component is something like `requiring-resolve`? Under the hood, it turns the var/symbol into a https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/lazy.clj#L22 and then invoked either https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/lazy.cljs#L31. I wasn't familiar with requiring-resolve, but I think the spirit is the same > do you use this call on the top level in your namespace? Yep, I define it at the top-level of the namespace via (def my-lazy-component (lazy/lazy-component components.huge-component-to-be-rendered-async)) > you can add `components.huge-component-to-be-rendered-async` to the `:exclude`-ed namespace of the unresolved namespace linter perhaps, or try this (experimental): I'll give this experimental route a try. Otherwise I'd have to add 20 or so namespaces to the exclusion list#2022-02-1115:16alex>
:config-in-call {your-ns/lazy-component {:linters {:unresolved-namespace {:level :off}}}}
Seems to be working well, thank you!
#2022-02-1115:17borkdudegreat to hear :)#2022-02-1111:48tomdI'd like to point flycheck-clj-kondo to a different config directory than the default (`.clj-kondo` in the root of the repo). Looks like there is a macro flycheck-clj-kondo-define-checkers but looks like it is already called at the bottom the package. Can I just call it again in my init.el with a --config-dir extra arg? I tried but it I think flycheck blew up.#2022-02-1111:51tomdlooks like I couldn't give it a ~ in the path. all fixed 🙂#2022-02-1115:44MaxIs there a way to add custom checks to clj-kondo? Say for example something simple like “don't import this library except in a specific ns”. I'm thinking about ways to guide devs towards the architectural happy path in a big project #2022-02-1115:46borkdude@max.r.rothman Custom checks can be added via hooks, but I don't think hooks currently work on the ns macro. You can however check all required libraries and where they are required in the analysis output and do your own validation on that. There is also an undocumented :custom-lint-fn which you can apply to all the analysis so you get the same kind of warning output you'd normally get. You can only use that on the JVM, not via the binary.#2022-02-1115:47borkdudeMore info here: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#2022-02-1115:48MaxThanks for the info! Out of curiosity do you know whether Clojure LSP uses the binary version? Editor integration would be a plus#2022-02-1115:50borkdudeyeah, but the custom-lint-fn isn't in anyway pluggable, with JVM I meant, as a JVM library, not as a command line tool. for editor integration I think we could either make a proper linter about what namespaces are allowed to be used in which namespaces or make the ns form "hook-able"#2022-02-1115:54borkdudee.g.:
{:forbidden-require {foo.bar [foo.baz]}}
or so
#2022-02-1115:55borkdudeI recommend using the analysis output first so you get a taste of this and then we can propose a linter for this#2022-02-1116:01MaxI’m less concerned with this specific example and more interested in general with being able to write custom lint checks that enforce project-specific constraints. Sounds like that’s currently possibleish but it’s not a super well-paved path?#2022-02-1116:04MaxHow likely do you think clj-kondo is to develop in any of these directions in the future? • Making ns hookable • Improving support/docs/guard rails for custom checks#2022-02-1116:05borkdudeThe data is all there, that is super well paved. You just have to write a small program which checks this data.#2022-02-1116:05borkdudeCustom checks are already well supported, just not in this specific example. There more you are willing to cooperate and provide input/feedback, the more likely this will become.#2022-02-1116:06MaxBy “a program which checks this data” do you mean a hook or a separate program that operates on analysis data?#2022-02-1116:07borkdudeCurrently, the latter. In the future, we could make a new hook for this which just gets to see the namespace requires, imports, etc and then you can do your own pass over that.#2022-02-1116:11borkdudeI think that hook could get the raw ns form + the parsed ns form as arguments which should make it easier to assert something#2022-02-1116:12borkdudeJust takes some work and hammock time to do this. Needs an issue. Perhaps if you're company has funds, sponsoring this could also help.#2022-02-1116:14MaxAh ok, I think I understand. Yeah probably all of the custom checks I’ve thought about can be implemented off of analysis data. I think the gap is integrating those custom checks into developer workflows, especially editors. Definitely as I get closer to actually building something I will file issues/make PRs/sponsor as appropriate, I’m currently just in the fact-finding phase#2022-02-1116:16borkdudeyeah, the editor integration will happen once you can make a hook that gets to see this data. see https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2022-02-1116:17borkdudewould it also help if you had a hook which only got to see the raw ns form? this can be very easily added#2022-02-1116:17borkdudebut the parsing of the ns form is a bit tedious and clj-kondo already does all of this#2022-02-1116:19borkdudebut we could definitely start with the raw form and add more things to it later#2022-02-1116:21MaxAre there other things that clj-kondo or analysis data are capable of doing that hooks are not?#2022-02-1116:22borkdudeprobably#2022-02-1116:24MaxIf it helps to make things concrete other examples of potential custom checks might include stuff like • don’t call that fn without wrapping it in a try • all the fns in this ns should contain a call to this other fn • Other kinds of “please use this correctly” guard rails#2022-02-1116:26borkdudeThe first one, clj-kondo is able to do this (it doesn't currently) but looking at the parent calls, these aren't exposed to hooks currently.#2022-02-1116:26borkdudeThe second one you could do with hooks, by just looking at the arguments#2022-02-1116:28borkdudehooks are mainly there to transform custom macros into known constructs, but slowly but surely extra things will be added to it.#2022-02-1116:29MaxOk, so if I’m going to summarize this particular fact finding mission, it sounds like the conclusion is: • clj-kondo definitely can support at least some (and probably many) custom rules via hooks • certain checks might require new development in clj-kondo, which should be supported appropriately • Probably anything you could want in a custom check is supported by operating on analysis data, but that approach won’t integrate well into developer workflows Does that sound correct?#2022-02-1116:30borkdudeCorrect#2022-02-1116:31MaxAwesome, thank you! This was really helpful#2022-02-1116:35Max…I guess I actually have one more question: would there be interest in clj-kondo growing a way to have integrated custom checks that run in the integrated SCI interpreter and operate on arbitrary analysis data? I think that’s different from a hook, but maybe it’s a special kind of hook? Does this question even make sense? The observation here is that analysis data can do anything but doesn’t integrate well into dev workflows, so I wonder if there’s a way to bridge that gap#2022-02-1116:36borkdude@max.r.rothman That's already what's happening, SCI is used to execute hooks. And yes, that's what I had in mind with exposing the parsed ns form as data in a hook.#2022-02-1116:37MaxGot it. Makes sense, thank you!#2022-02-1116:39borkdudeThe general format with hooks is map in, map out and node is just one part of the map in/output. There can be many more things added over time.#2022-02-1313:34borkdude@max.r.rothman Hmm, it seems hooks are available on namespace forms already: https://twitter.com/FourPillTherapy/status/1492831326680059911 So I guess you can already do a lot of what you want, using the raw ns form node.#2022-02-1316:47MaxNice!#2022-02-1115:50Sam RitchieHey all! I am seeing an issue with clj-kondo where, in a cljc file, kondo does not peer inside the :clj branch of my form:#2022-02-1115:50Sam RitchieThis triggers an unused binding warning on clj-kondo v2022.02.09.#2022-02-1115:51borkdudeThis has always been the behavior. The binding is unused in the cljs form, so the warning applies to the cljs behavior.#2022-02-1115:51borkdudeYou can do #?(:cljs _f :clj f) to fix this warning#2022-02-1115:52Sam Ritchienice, thank you!#2022-02-1115:53Sam Ritchiedo you like _f vs #?(:cljs _ :clj f) so that the symbol is at least sort of self documenting if you want to use it later?#2022-02-1115:53borkdudeno preference#2022-02-1115:53Sam Ritchiefixing these warnings is addictive…#2022-02-1511:40mkvlris there a way to opt out of this behavior? Making the code more complex by introducing another reader conditional just to fix the unused var warning doesn’t seem right to me. I don’t see the benefit of having this be a warning or am I missing something? Since _ isn’t treated special in Clojure there’s zero difference in performance or behaviour, right?#2022-02-1511:41borkdudeAn unused binding in one target, but not in the other target is usually a sign that you forgot something in handling the other target. This behavior has been in clj-kondo since the very start and intentional.#2022-02-1511:41borkdudeThere is no option to opt out of it.#2022-02-1511:50borkdudeI think the first step should be to add the target to the warning message: unused binding [cljs] or so. since it sometimes confuses people why the binding was unused if it's used e.g. only in clj but not in cljs#2022-02-1511:50borkdudethere is already an issue for this#2022-02-1511:54mkvlrbut you think it’s useful in general? Looking at the code holistically (cljc) it’s not unused.#2022-02-1511:55mkvlrI’ll comment on the issue#2022-02-1511:56borkdudeclj-kondo views .cljc files as actually two (or more) files: one for each platform and lints those separately. which issue?#2022-02-1511:57mkvlrsearching for the issue you mention in https://clojurians.slack.com/archives/CHY97NXE2/p1644925841686819?thread_ts=1644594623.137069&amp;cid=CHY97NXE2 now#2022-02-1511:58borkdudeThat issue is about the reporting. https://github.com/clj-kondo/clj-kondo/issues/1196#2022-02-1511:58borkdudeI'm not entirely convinced that adding a config to suppress stuff based on one target is a good idea.#2022-02-1511:59borkdudeE.g. if you have an invalid arity call in .clj, but not in .cljs, would you not emit it because it's valid in just one target?#2022-02-1512:00mkvlrI’d argue that it shouldn’t be a warning, but only this specific case, unused var. Feels like the game of pleasing the linter, without an actual improvement to how my code behaves.#2022-02-1512:01mkvlrinvalid arity is very different in this regard.#2022-02-1512:01borkdudeAs I said, it's often an oversight when a binding is used in only one target, so I don't really agree with that it's only pleasing the linter. Can be, doesn't have to be, as always with linting.#2022-02-1512:02borkdudeI personally wouldn't use this option, if it existed.#2022-02-1512:04mkvlr> Can be, doesn’t have to be, as always with linting. Surely this doesn’t apply to everything condo reports? A lot of things are almost certainly problems?#2022-02-1512:05borkdudeAn unused binding isn't a problem to begin with.#2022-02-1512:06borkdudeYou can also just disable it in a .cljc file if it's too much#2022-02-1512:06mkvlrtrue#2022-02-1117:25Sam Ritchiequestion - when I am developing a custom config to export from a library… should the config I’m adding in resources be automatically picked up? Or do I have to add it to my config.edn in the library root#2022-02-1117:26borkdude@sritchie09 You'll have to add it to config.edn in the root via :config-paths ["../resources/clj-kondo.exports/foo/bar"]#2022-02-1117:26borkdudeand then you can develop the exported config in resources to avoid duplication#2022-02-1117:29Sam Ritchiethank you!#2022-02-1117:44Sam Ritchie{:lint-as {sicmutils.util.def/import-def potemkin.namespaces/import-def}} does seem to be having trouble, even though clj-kondo seems to know about potemkin just fine#2022-02-1117:44Sam Ritchiemaybe I need to use some other way of importing the config?#2022-02-1117:44borkdudeimport-def might not be supported, import-vars is#2022-02-1117:45borkdudebrb, dinner#2022-02-1117:45Sam Ritchiesg#2022-02-1118:16Sam Ritchiefor when you are back… is it important, when writing a hook that expands from, say,
(with-literal-functions [x y] ...)
to
(let [x (literal-function 'x) y (literal-function 'y)] ...)
to generate the full expansion? or is
(let [x nil y nil] ...)
sufficient?
#2022-02-1118:59borkdudeIt depends, expanding to the latter might result in unused literal function var warnings, but depending on the context, that may not matter#2022-02-1119:05Sam Ritchie👍#2022-02-1118:40Stan FoleyHi#2022-02-1118:41Stan FoleyI get a compiler error with the project that I cloned, and I was told that the question might be more relevant to this room. Can someone have a look please?#2022-02-1118:58borkdudeCan you explain how a compiler error relates to #clj-kondo?#2022-02-1119:06Stan FoleyHi#2022-02-1119:07Stan FoleyI am new,and I was in another room. I was told that this room is more relevant to speclj#2022-02-1119:09Stan FoleyI know nothing about clj-kondo. I was told that speclj is related to it. If that is wrong I'll jump out, and I appologize for troubling you#2022-02-1119:12Stan FoleyOh they told me that the linter complains about :refer :all and this room might know more about it#2022-02-1119:36Stan FoleyI was able to run it. Thank you and sorry for borthering you for nothing. I am reading the docs.#2022-02-1119:46borkdude@U032K6B0EEA Ah I see. It's about the unresolved symbols. Normally those should go away when your dependencies are linted. Are you using Calva?#2022-02-1119:50borkdudeI see the issue. So the solution is to open each sub-project in the right root, where the project.clj is. Then #lsp will index the dependencies and the :refer :all is understood.#2022-02-1119:59borkdudehttps://ask.clojure.org/index.php/11564/need-help-with-compiler-error-unresolved-symbol?show=11568#a11568#2022-02-1202:38Stan FoleyHi. yes I am using Calva, and ok I'll open the projects separately. Thank you so much for the reply. Calva is just amazing, and so is Clojure. They make short work of some very useful functionalities.#2022-02-1118:42Stan FoleyI cloned it from : https://github.com/unclebob/Euler#2022-02-1119:06Sam Ritchieso close to killing all warnings. A HAIRY macro, I think, is this one: https://github.com/sicmutils/sicmutils/blob/main/src/pattern/rule.cljc#L92-L101 which basically expands to a call to compile-pattern here: https://github.com/sicmutils/sicmutils/blob/main/src/pattern/syntax.cljc#L208 which does selective quoting and rewriting of the form. Luckily this is a small namespace, so I can copy the whole thing into the hook if I need to, AND rewrite it to operate on the clj-kondo internal representation. Is there instead some way to get the hook to run that particular namespace?#2022-02-1119:59borkdudeLet's see#2022-02-1120:00borkdudeI don't really know what to make of this unless I also see example calls#2022-02-1120:23Sam Ritchiesorry, pitiful bug report!#2022-02-1120:26Sam Ritchie@U04V15CAJ SO, what the internal compile-pattern does is scans its incoming forms and handles various cases like:
- `(? x) => (list '? 'x)`
  - `(?? x) => (list '?? 'x)`
  - `($$ x) => (list '$$ 'x)`
  - any unquoted symbol is quoted
  - Any form unquoted like `~x` is left UNquoted
  - Any form marked `
#2022-02-1120:26Sam Ritchiethat requires walking the incoming syntax tree and performing various substitutions, dropping down recursively into any sequences or maps#2022-02-1120:27borkdudebut what linting errors does it actually cause? those might be easy to prevent regardless of what the macro does#2022-02-1120:28Sam Ritchieyup, writing this up is helping me realize that there might be a simpler way. The main error is “unresolved symbol”;#2022-02-1120:28borkdudedo you have an actual example call?#2022-02-1120:28Sam Ritchieyes, getting it together now#2022-02-1120:29Sam Ritchiehere is a 1-nested pattern:#2022-02-1120:29Sam Ritchie#2022-02-1120:29Sam Ritchieso, yes… I think I am seeing the simpler form#2022-02-1120:30Sam Ritchieany symbol should NOT ever trigger an unresolved symbol error;#2022-02-1120:30Sam Ritchieunless it is inside a splice form like#2022-02-1120:31Sam Ritchie#2022-02-1120:32Sam Ritchieso what I’m realizing (duh) is that it might be that a much simpler walker that just quotes everything except stuff inside splices or unquote-splices will do it#2022-02-1120:32borkdudewhat you could do is write a hook that ignores every question marked symbol, or just ignore all unresolved symbol errors whatsoever by configuring :linters {unresolved-symbol {:exclude [(your-ns/pattern)]}}#2022-02-1120:35borkdudethe latter is the quick solution#2022-02-1120:36Sam Ritchieyup, but in this case I DO want to have the unresolved symbol error on expected in that last example#2022-02-1120:36Sam Ritchie#2022-02-1120:36Sam Ritchie@U04V15CAJ I think I haave the answer so don’t let me take your time here#2022-02-1120:36borkdudewhat you can do is walk the body, select all unquoted expressions and then return a vector node of those#2022-02-1120:37Sam Ritchieoh, I like that#2022-02-1120:37borkdudeI have a similar macro in babashka.process, called $ which also uses unquote in this way#2022-02-1120:38Sam Ritchieso by returning the vector, everything in the vector will get hit with the linter#2022-02-1120:38Sam Ritchiebrilliant…#2022-02-1120:38borkdudeyeah#2022-02-1120:39Sam Ritchienow that I’m started on this, it’s super fun writing hooks etc#2022-02-1119:07Sam Ritchiesecond Q, so not threading… I am getting warnings from data_readers.clj. is there a way to turn these off… OR is it correct that I should be calling require in my data_readers file?
src/data_readers.cljc:1:2: warning: Unresolved namespace sicm. Are you missing a require?
src/data_readers.cljc:1:18: warning: Unresolved namespace sicmutils.util. Are you missing a require?
src/data_readers.cljc:2:18: warning: Unresolved namespace sicmutils.ratio. Are you missing a require?
src/data_readers.cljc:3:18: warning: Unresolved namespace sicmutils.complex. Are you missing a require?
src/data_readers.cljc:4:18: warning: Unresolved namespace sicmutils.quaternion. Are you missing a require?
#2022-02-1120:00borkdudeHm no, this should be fixed in clj-kondo. issue welcome#2022-02-1120:01borkdudeOh, there is already an issue for it: https://github.com/clj-kondo/clj-kondo/issues/892#issuecomment-803461457 I will bump priority#2022-02-1121:07Sam Ritchiehere is a potential bug:#2022-02-1121:07Sam Ritchiethis is a reader literal defined as:#2022-02-1121:07Sam Ritchie
(defn parse-bigint [x]
  `(bigint ~x))
#2022-02-1121:08Sam Ritchie#2022-02-1121:08Sam Ritchieso the macroexpansion checks out fine, but not the reader-literal wrapper#2022-02-1121:10Alex Miller (Clojure team)if you're expecting #sicm/bigint one-e-40 to eval that, that is not how reader literals work#2022-02-1121:11Alex Miller (Clojure team)but I'm not sure what you think is the bug here#2022-02-1121:11Sam Ritchie@alexmiller my thought was that reader literals are only supposed to do a minimal code transform, NOT to actually evaluate to a bigint#2022-02-1121:11Sam Ritchie(in this case)#2022-02-1121:11Sam Ritchie(=> thread)#2022-02-1121:12Alex Miller (Clojure team)can you post it w/o the images - I literally can't see all of that stuff at the same time#2022-02-1121:12Sam Ritchieyeah, sorry#2022-02-1121:12Alex Miller (Clojure team)reader literals happen at read time so the reader literal function is passed unevaluated values#2022-02-1121:13Sam Ritchie
;; I'm using this reader literal because I need cljs to produce a `js/BigInt`,
;; and there is no `bigint` function that will do that for me:
(let [one-e-40 (apply str "1" (repeat 40 "0"))]
  #sicm/bigint one-e-40)
#2022-02-1121:13Sam Ritchie@alexmiller yes, so for clojurescript I need to emit (js/BigInt form) for #sicm/bigint form#2022-02-1121:14Sam Ritchiebut for clj I could of course just emit a BigInt instance, since I’m on the JVM#2022-02-1121:14Sam Ritchie(maybe the cljs angle explains why I am emitting (u/bigint form) , and in turn why I was expecting #sicm/bigint one-e-40 to work#2022-02-1121:15Alex Miller (Clojure team)I know this has been an area of discussion in cljs lately, not sure what current state is, but might need to check in #cljs-dev#2022-02-1121:16Alex Miller (Clojure team)certainly for Clojure, this looks all wrong, but I don't know what to expect with cljs right now#2022-02-1121:17Sam RitchieIt's weird, but it DOES work - and I did it to make behavior the same one both sides #2022-02-1121:17Sam RitchieBut yeah worth digging #2022-02-1121:21borkdude@alexmiller That's what I thought too, but when another user brought this up recently, and I tested it, I thought clj-kondo was wrong: https://github.com/clj-kondo/clj-kondo/issues/1579#2022-02-1121:21borkdudeFeel free to chime in in that issue!#2022-02-1121:22borkdudeI made a fix regarding data literals when someone has #foo ([dude]) where clj-kondo linted it incorrectly as a vector being called as a function. After that fix, the expression is basically handled as a quoted expression. But apparently this is also not how it works.#2022-02-1121:24Alex Miller (Clojure team)I know Henry Widd has been advocating for changes in this area for a while to get the ability to do platform specific reader literal stuff (https://clojure.atlassian.net/browse/CLJS-3294 at least), not sure what the outcome of all that was in CLJS#2022-02-1121:25borkdudeWhat does that have to do with the above issue?#2022-02-1121:25borkdudeI tested the above on JVM Clojure#2022-02-1121:25Alex Miller (Clojure team)I don't know exactly, I just know that he's been trying to make cross platform data readers work#2022-02-1121:27borkdude@sritchie09 Let's go into a thread. This is a repro I tried on the JVM:
(set! *data-readers*
      (assoc *data-readers* 'time/date identity))

(let [foo "2022-02-10"
      bar #time/date foo]
  (prn bar))
#2022-02-1121:27Sam RitchieSg#2022-02-1121:28Sam RitchieNice, way tighter . I'm away from keyboard now - does it show the same behavior?#2022-02-1121:29borkdudeeven:
(def foo 1)
(let [bar #time/date foo]
  (prn bar))
returns 1
#2022-02-1121:30Sam RitchieBut does clj-kondo Think that foo is unused in this case? #2022-02-1121:31Alex Miller (Clojure team)that that prints 1 instead of foo is I think an accident of implementation and where evaluation happens#2022-02-1121:31Alex Miller (Clojure team)well, maybe not#2022-02-1121:31Alex Miller (Clojure team)I guess I'd expect bar to be bound to the symbol foo#2022-02-1121:32borkdude> But does clj-kondo Think that foo is unused in this case? Before the latest release it it didn't, but because of a fix for this issue: https://github.com/clj-kondo/clj-kondo/issues/1563 it now basically treats the "data" as a quoted expression.#2022-02-1121:33Alex Miller (Clojure team)imo, that is correct in CLJ#2022-02-1121:33Sam RitchieI think I disagree because of what happens when you put an explicit quote in the argument to a reader literal #2022-02-1121:33Alex Miller (Clojure team)the #time/date fn is called during read with unevaluated values#2022-02-1121:34Sam Ritchie I’ll pick back up when I’m not a distracted passenger in the car, thanks to you both for looking at this! #2022-02-1121:35Sam RitchieBut the return value is treated like the return value from a macro#2022-02-1121:35Alex Miller (Clojure team)if so, that is accidental implementation in CLJ (but I think is expected in CLJS)#2022-02-1121:35Alex Miller (Clojure team)this is where the platforms differ#2022-02-1121:36borkdudeI'll just relax the linting in clj-kondo in accordance with the accidental implementation, since people seem to rely on this....#2022-02-1121:37Alex Miller (Clojure team)well, they shouldn't and they could be broken in the future#2022-02-1121:37Sam RitchieAlex, the current implementation matches how the vector literal and map, set etc work right?#2022-02-1121:38Alex Miller (Clojure team)those are different - literal colls evaluate their elements#2022-02-1121:38Sam Ritchie#sicm/quaternion [a b ‘x ‘y] was a place where I was relying on this #2022-02-1121:39Sam RitchieFirst two elements were let bound, the third and fourth are explicit quoted symbols #2022-02-1121:39Sam Ritchie(Since I can do symbolic arithmetic)#2022-02-1121:39Alex Miller (Clojure team)https://clojure.org/reference/evaluation "Vectors, Sets and Maps yield vectors and (hash) sets and maps whose contents are the evaluated values of the objects they contain."#2022-02-1121:40Sam RitchieTotally, and evaluation in this case makes bar bind to 1 like it does now #2022-02-1121:40Sam RitchieWhereas Unevaluated would be the symbol foo#2022-02-1121:40Alex Miller (Clojure team)https://clojure.org/reference/reader#tagged_literals "The data reader function is invoked on the form AFTER it has been read as a normal Clojure data structure by the reader." (notably no evaluation mentioned here)#2022-02-1121:40Alex Miller (Clojure team)so you're talking about the combination of these#2022-02-1121:41Alex Miller (Clojure team)....#2022-02-1121:41Sam Ritchieyes, so the symbol (unevaluated) is passed in, and then the returned form is evaluated. Which matches my mental model that [] expands to a call to “vector”#2022-02-1121:42Alex Miller (Clojure team)not a great model but maybe ok#2022-02-1121:42Sam Ritchieokay, got a keyboard for a moment#2022-02-1121:42Alex Miller (Clojure team)I guess the combination of the things above would imply evaluation of the literal vector at read time before being passed to the reader fn#2022-02-1121:43Alex Miller (Clojure team)I would say this is certainly not the intent of the reader fn, which is to take primitive data values to describe new complex data values#2022-02-1121:43Sam Ritchie@alexmiller hmm, it is quite useful for sure to be able to make compound values too#2022-02-1121:44Alex Miller (Clojure team)that's what functions are for#2022-02-1121:44Sam Ritchietrue 🙂#2022-02-1121:44Alex Miller (Clojure team)it's not data anymore#2022-02-1121:44Alex Miller (Clojure team)I can't stick it in an edn file and read it elsewhere#2022-02-1121:44Sam Ritchiethe reason I was doing all this was so I could have a printable representation that someone could evaluate#2022-02-1121:45Alex Miller (Clojure team)which is fine#2022-02-1121:45Sam Ritchieso quaternions are 4-vectors, but they print like #sicm/quaternion [r i j k]#2022-02-1121:45Alex Miller (Clojure team)that seems fine#2022-02-1121:45Alex Miller (Clojure team)it's the evaluation in the constructor that's fishy#2022-02-1121:45Sam Ritchiewhich you can then paste in; which works with primitives, I see what you’re saying#2022-02-1121:45Sam RitchieI think I am explicitly NOT evaluating in the constructor#2022-02-1121:45Alex Miller (Clojure team)what are a and b here then? #sicm/quaternion [a b 'x 'y]#2022-02-1121:46Sam Ritchiesay, 1 and 2; but the emitted form from that is just (quaternion a b 'x 'y)#2022-02-1121:46Alex Miller (Clojure team)that's not data#2022-02-1121:46Alex Miller (Clojure team)I'd say use the function in that case#2022-02-1121:46Sam Ritchieso reader literals should always emit data;#2022-02-1121:46Alex Miller (Clojure team)literal#2022-02-1121:46Sam Ritchieand it’s an accident now that they can emit code forms, like a macro?#2022-02-1121:47Alex Miller (Clojure team)it's an accident that that "works"#2022-02-1121:47Sam RitchieI totally get it, we are clashing on my model of [a b c] expanding to (vector a b c)#2022-02-1121:47Sam Ritchiewhich works, even when a b and c are bound outside of [a b c]#2022-02-1121:47Alex Miller (Clojure team)if you want a macro, make a macro#2022-02-1121:48Sam Ritchie👍#2022-02-1121:48Sam Ritchieokay, thanks for talking it out#2022-02-1121:48Sam Ritchieit might be an accident, but it is a nice feature 🙂#2022-02-1121:48Alex Miller (Clojure team)you should be able to take the thing that is a data reader and read it in another jvm and get a value#2022-02-1121:48Alex Miller (Clojure team)it's bad and you should feel bad :)#2022-02-1121:49Alex Miller (Clojure team)it's basically reader macros, which are intentionally not a feature in Clojure#2022-02-1121:49Alex Miller (Clojure team)and this has come up before in cases where it didn't work like someone expected (don't remember the context now)#2022-02-1121:49Alex Miller (Clojure team)but it was something Henry was doing#2022-02-1122:04borkdudeSo, is the summary: it works (similar to macro-expansion), but it's not how it's intended to be used in JVM Clojure, but in CLJS it is explicitly supported?#2022-02-1122:13Alex Miller (Clojure team)yes for the CLJ parts, I think for the CLJS parts but I would verify that with dnolen#2022-02-1122:14borkdudeSo the gist is: data readers should be used to read context-free data.#2022-02-1122:15Alex Miller (Clojure team)or reader literals are literals#2022-02-1122:15borkdudeSo the current take of clj-kondo on this aligns with how it's intended (at least on the JVM)#2022-02-1122:15Alex Miller (Clojure team)I think so#2022-02-1210:34henryw374feel my ears burning 🙂 to explain what the change is that I was advocating for (and has recently been merged to cljs master). A data_readers.cljc file with the following content: {foo/bar #?(:clj xx/yy :cljs ff/gg)} is read by the clojure compiler ok (and it reads the :clj branch). The cljs compiler did not have conditional read enabled so would barf on that. With the change, the cljs compiler reads the :cljs branch. That's it really - so no change to how data reader functions work#2022-02-1210:38borkdudeok. I wonder how clj-kondo could help with promoting the idea of reading literals instead of expressions that depend on context, but this depends on what the reader function does and clj-kondo cannot know this#2022-02-1210:45henryw374hmm, probably I'm being naive but in #foo/bar a it must see that a is not a literal#2022-02-1210:46borkdudeno! the point is that a could be a literal and should be handled as a literal by the reader function, but often is not, because people are abusing reader functions as macros#2022-02-1210:47borkdudeHopefully I'm paraphrasing correctly, what Alex explained in this thread#2022-02-1210:54henryw374ok. I can't think I would write something like #foo/bar a in code. I would think it better style to just call the function. again repeating what's been said above, but reader functions targeting cljs (written in clojure) are often necessarily macro-like (as per one emitting
(js/BigInt ~x)). 
mentioned somewhere in the thread)
#2022-02-1211:07borkdudeWhy is that necessary (instead of just calling a function or macro)?#2022-02-1211:07borkdudeAnd how is that unique to CLJS?#2022-02-1211:08borkdudebecause the reader runs on the JVM but the code produced runs in JS?#2022-02-1211:09henryw374Yes, exactly that#2022-02-1211:11henryw374But note a reader function intended to run in a js env, such as when reading edn, will not be macro like#2022-02-1211:14borkdudeso when do you need a reader function for this rather than a macro? as in, the necessary part?#2022-02-1211:17borkdudeor even a function#2022-02-1211:22henryw374for me personally I use cljs data literals in the repl. the tags round trip via printer. so e.g. calling some fn that prints out #foo/bar "abc" , then I'll want to paste that back in. I don't think I would ever put a tagged literal in a source file#2022-02-1211:34henryw374for one thing, in clojure, you have to make sure the reader function exists already, or else the reader will complain. iow you have to require the reader function ns in any ns where you use the literal. so if you have to do that, you might as well call the fn directly imo#2022-02-1211:36borkdudewhat is the point with the last issue?#2022-02-1211:37borkdudeI don't see how it relates to "read only literals, not context-sensitive expressions", could you explain?#2022-02-1211:46henryw374well my feeling is the context sensitive thing would only come up in source code. and ofc that's what kondo is for 🙂 . I guess I'm saying if kondo complained error: tagged literal in source code then I would be happy#2022-02-1211:50borkdudeisn't that the main idea behind data_readers.cljc though, that you can use it in source code? ;)#2022-02-1212:21henryw374well I only want to use when interacting with the REPL. I appreciate others may feel differently. and I would be interested to hear arguments for having them in source code. I mean, there's usually little in it verbosity-wise and tagged literals intentionally add indirection-- but I don't want that indirection in source#2022-02-1214:28Sam Ritchie@U051B9FU1 one spot I am abusing this is to get ratio support in Clojurescript; I do have #sicm/ratio 1/2 forms in my source that can actually product (rationalize (bigint 1) (bigint 2)) in cljs because, by running on the JVM side, the 1/2 reader literal actually makes sense#2022-02-1214:28Sam Ritchiethat’s the only spot where it would be aesthetically blah to switch to (ratio 1 2) all over (though (/ 1 2) when I have my overriding / imported, so even that is not so bad#2022-02-1220:24henryw374thanks @sritchie09 - personally I'd go with the fn call style you mention but appreciate that's personal preference. Slight digression but I certainly wouldn't put them in library source as I think end user should have full control over reading and printing. but would you do #sicm/ratio foo though if it was written in macro style? & back to clj-kondo and discouraging macro-style reader functions @U04V15CAJ I still think kondo could report on usage such as
#foo/bar a 
I see that given:
(let [x "2022"]
  #inst x)
kondo reports warning: unused binding x . this particular code doesn't compile with the default Clojure/script binding of #inst , because the reader fn is not in macro-style, but kondo can't know that I guess, but as per my suggestion it might say don't pass variable to tagged literal, just call the fn/macro directly
#2022-02-1220:27borkdudeclj-kondo cannot know if you're passing x as a contextual value or as a literal. the reader function always sees the literal symbol x - it's up to that function what to do with it and this is opaque to clj-kondo.#2022-02-1220:27borkdudeso x might be really unused, depending on what the reader function expands into#2022-02-1220:28borkdudeso clj-kondo cannot reliably warn against something here#2022-02-1221:10henryw374Ok, I'm sure you're right!#2022-02-1221:16borkdude@U051B9FU1 it's the same with:
(defmacro foo [x] ...)
The macro could be doing:
(list 'quote x)
So then (let [g 1] (foo g)) here g is unused, even though its name was passed to the macro.
#2022-02-1221:17borkdudesymbols are data and data reader function could treat those just as literal symbols, which makes things almost impossible to statically analyze, unless clj-kondo had a config for data reader function expansion like it has for macros, I guess it could add that, but not sure how useful it would be#2022-02-1221:36henryw374I'm struggling to think why you might pass a valid variable symbol to a reader function that would treat it just as a symbol.#2022-02-1221:37henryw374But who knows#2022-02-1222:02borkdudewell, given examples like:
#garden.types.CSSAtRule {:identifier :media
                             :value {:media-queries {:min-width "768px"}
                                     :rules ([".md\\:container" {:max-width "768px"}])}}
(note: :rules is not evaluated, else the vector would be alled as a function with no args, resulting in a read time error) it might not be far fetched that there can be random symbols in chunks like that, e.g. :id foobar
#2022-02-1222:03borkdudeI think the best clj-kondo can do here, might be to not emit any warnings on code that could be valid Clojure, getting out of the way#2022-02-1318:49henryw374yeah makes sense. :thumbsup:#2022-02-1121:27Sam RitchieActually, @alexmiller what was weird about my example in your mind?#2022-02-1121:28Alex Miller (Clojure team)it looked like you were expecting one-e-40 to be evaluated when I expect it (in CLJ) to just be passed as a symbol to the reader literal function. and reader literal functions should return a value, not an expansion.#2022-02-1121:29borkdudeCan we continue in the thread above, to reduce noise for others not interested in this?#2022-02-1121:42zaneWhat determines the Clojure version clj-kondo lints against? It doesn’t appear to be the one in deps.edn.
❯ clj
Clojure 1.10.3
user=> abs
Syntax error compiling at (REPL:0:0).
Unable to resolve symbol: abs in this context
❯ clj-kondo --lint src
src/….clj:8:1: warning: abs already refers to #'clojure.core/abs
linting took 594ms, errors: 0, warnings: 1
#2022-02-1122:06borkdude@zane clj-kondo's built-in cache has a recent version of clojure (alpha3, I realize it needs bumping), but if you lint your deps, including your used clojure, then you get what you're really using.#2022-02-1122:16zane@U04V15CAJ How do I go about linting my deps, including my used clojure? I’m launching it from the same directory as the deps.edn and have tried --lint . and --lint deps.edn ….#2022-02-1122:17borkdude@zane clj-kondo --lint $(clojure -Spath) --dependencies#2022-02-1122:18borkdudeThe --dependencies flag will take care of a few things: 1. it won't emit any warnings 2. it will not re-lint jar files it's already seen#2022-02-1122:18zaneI see!#2022-02-1122:18zaneThanks!#2022-02-1122:23zaneWould you recommend --dependencies in CI, then?#2022-02-1122:30borkdudeFor better linting results, it does provide benefits, e.g. you will see invalid arity calls to third party deps, but it's also totally fine to not do this.#2022-02-1122:31borkdudeyou can cache the linting results though, if you're deps.edn didn't change#2022-02-1122:31borkdudeand then the second time should be faster, if that's a concern#2022-02-1200:42Sam Ritchiepotentially silly Q - if I have a dependency like https://github.com/gfredericks/test.chuck that has its own clj-config in it, how can I get clj-kondo to see that dependency? I’ve bumped the dep in project.clj;#2022-02-1200:43Sam Ritchiebut I also have a deps edn so I suspect kondo is looking there. but under what alias?#2022-02-1200:43Sam Ritchie(since I don’t want to declare this as a dependency that others have to pull when they pull the library)#2022-02-1201:12dorabPerhaps https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#importing is of help?#2022-02-1201:15dorabI think you might be able to generate an appropriate classpath for clj-kondo by using the appropriate deps. (Don't know or sure. Just suggesting avenues to look at).#2022-02-1201:18Sam Ritchiefor sure, that is what I was counting on, I am just not sure how clj-kondo is building its classpath…#2022-02-1201:40dorabThe example command in the section of the documentation is $ clj-kondo --copy-configs --dependencies --lint "$(clojure -Spath)". So, I'm guessing that the classpath is actually generated by "$(clojure -Spath)" and you could change that to "$(clojure -Spath -A:test)"#2022-02-1201:41dorabOn second thoughts, I'm not sure I'm answering the question you are asking. Sorry.#2022-02-1209:27borkdudeIndeed, @U0AT6MBUL’s correct#2022-02-1205:19Sam RitchieIs it possible to emit a binding form like (let [x 'x y 'y z 'z] …) from a hook… but to suppress any unused binding warnings with metadata applied inside the hook?#2022-02-1205:23Sam RitchieI have a macro that expands calls like this:
(let-coordinates [[x y z] m/R3-rect
                  [x0 y0] m/R2-rect]
  (+ x y z))
into this (the actual macro does more with the values of course):
(let [R3-rect (quote R3-rect)
      R2-rect (quote R2-rect)
      x (quote x)
      y (quote y)
      z (quote z)
      x0 (quote x0)
      y0 (quote y0)
      d:dx (quote d:dx)
      d:dy (quote d:dy)
      d:dz (quote d:dz)
      d:dx0 (quote d:dx0)
      d:dy0 (quote d:dy0)
      dx (quote dx)
      dy (quote dy)
      dz (quote dz)
      dx0 (quote dx0)
      dy0 (quote dy0)]
  (+ x y z))
the idea is that all of these symbols will be bound and available inside of the binding, but if they’re not used, no problem. I am seeing lots of warnings like
src/sicmutils/calculus/coordinate.cljc::: warning: unused binding R2-rect
src/sicmutils/calculus/coordinate.cljc::: warning: unused binding d:dy0
src/sicmutils/calculus/coordinate.cljc::: warning: unused binding dy0
src/sicmutils/calculus/coordinate.cljc::: warning: unused binding d:dx
#2022-02-1205:24Sam Ritchieso ideally I would suppress all of them, or maybe all except the ones that appear in the initial form like x y z x0 y0… but the linted version is still quite useful, since inside the body d:dt etc will not show up as unresolved symbols#2022-02-1207:01borkdudeYes, just use the bindings once in the body#2022-02-1207:13Sam Ritchieah! nice, so just emit the full list of them in a vector, for example?#2022-02-1207:49Sam Ritchieworked great!#2022-02-1303:33Sam Ritchieis there a way to see the namespace that is currently being linted, from a hook? I am looking to suppress this error:
test/sicmutils/fdg/ch10_test.cljc::: warning: redefined var #'sicmutils.fdg.ch10-test/spherical
which happens because this form:
(define-coordinates [r theta phi] spherical)
expands into:
(let* [G__57649 (with-coordinate-prototype spherical ['r 'theta 'phi])]
  (def spherical G__57649)
  ...)
This overwrites the spherical binding, of course, but that’s the intent of this form. So my thought was that my hook could just NOT emit the def if the symbol is already bound in the namespace. But maybe there is a better way to suppress?
#2022-02-1303:34borkdudeCheck all the keys in the hook arg, it nay already be in there #2022-02-1303:35Sam Ritchie@borkdude ugh, I printed the whole thing before and didn’t see :namespace but of course it’s here as :ns. I’m making a strong effort to not waste your time here, I promise!!#2022-02-1303:37Sam Ritchie@borkdude but while I have you, I was thinking that one nice function in a hook would be something like fmap ; the pattern of (api/token-node (f (:value node))) , (api/list-node (f (:children node))) etc would be instead (api/fmap f node) in both cases#2022-02-1303:38Sam Ritchiepowered by a protocol offering fmap* or something so you could correctly dispatch on the non-function arg#2022-02-1305:33Sam Ritchie@borkdude it won’t quite work due to caching, I think. here is what I tried:
(defn define-coordinates [{:keys [node ns]}]
  (let [[_ _ system] (:children node)
        analysis (api/ns-analysis ns)
        existing (into (set (keys (:clj analysis)))
                       (keys (:cljs analysis)))
        sys-name (api/token-node (symbol (name (:value system))))
        new-node (api/list-node
                  (concat
                   [(api/token-node 'do)]
                   (when-not (existing (:value sys-name))
                     [(api/list-node
                       [(api/token-node 'def) sys-name system])])))]
    {:node new-node}))
the first time I run the linter, given some form like
(define-coordinates t e/R1-rect)
the linter runs with no warnings (but internally (def R1-rect e/R1-rect) is emitted). So next time I run the linter, (api/ns-analysis ns) shows that the binding exists, since the linter emitted it last time… which means that this form will NOT be present the second time, causing error: Unresolved symbol: R1-rect farther down in the file
#2022-02-1309:10borkdudeWhy is this linting conditional on things existing prior to it?#2022-02-1313:23Sam RitchieMy intent is to be able to let the user write:
(ns sicm.example
  (:require [sicmutils.calculus.manifold :refer [R2-rect]]))

(define-coordinates [x0 y0] R2-rect)
and not trigger warning: R2-rect already refers to #'sicmutils.env/R2-rect ; so this was my guess at how to do that, by checking what existed in the incoming state and reacting. (you could argue that it IS a good warning and the user should absolutely not do a bare R2-rect import then overwrite it, and I AGREE… except that to be compatible with all of the scheme code this is mirroring, the user gets an environment with everything exposed, then can rebind stuff selectively with define-coordinates. The reason you’d do that is basically to give the coordinates names, like x y z.)
#2022-02-1313:24Sam Ritchie@borkdude another way to handle this would be
#_{:clj-kondo/ignore [:redefined-var]}
(define-coordinates [x0 y0] R2-rect)
but strangely that doesn’t seem to kill the warning. it DOES if I paste in the macroexpansion directly:
#_{:clj-kondo/ignore [:redefined-var]}
(let* [G__43077
       (sicmutils.calculus.manifold/with-coordinate-prototype R2-rect ['x0 'y0])]
  (def R2-rect G__43077))
#2022-02-1313:39borkdudewhy not (declare R2-rect) ?#2022-02-1313:40Sam Ritchiegenerate that inside the hook, you mean?#2022-02-1313:43borkdudeyeah, then that won't trigger a redefined var warning#2022-02-1313:43Sam Ritchieinteresting, that almost works, and the reason why not is because I didn’t think of it 🙂#2022-02-1313:44Sam Ritchiealmost because now we get this:
#'sicmutils.env/R2-rect is referred but never used
from
(ns sicm.example
  (:require [sicmutils.env:refer [R2-rect]]))

(define-coordinates [x0 y0] R2-rect)
#2022-02-1313:44borkdudeyou can just generate another usage after that#2022-02-1313:45Sam Ritchiegot it, so generate all the declares, and also a vector of all of the syms#2022-02-1313:45borkdude
yes
#2022-02-1313:45Sam Ritchieawesome, I’ll try that soon. thanks!#2022-02-1313:45borkdudeor you can generate something like potemkin import-vars which will then treat those defined vars as the imported vars with respect to arity, etc#2022-02-1313:46Sam RitchieI’m getting the hang of this. next @borkdude is to go document my hooks well and emit more custom warnings etc from the body#2022-02-1313:46borkdudesince there is built-in support for potemkin#2022-02-1313:46Sam Ritchie@borkdude is it the case that to make that work, I’d again be in the position of having to know which ones were being declared for the first time and which were overwriting?#2022-02-1313:49borkdudeyeah I think so#2022-02-1303:47Sam Ritchieis it possible to access other namespaces than hooks-api in hooks? I think no; but for this particular task, I think I need unquote-node and unquote-splicing-nodehttps://github.com/clj-kondo/clj-kondo/blob/d3c39e7f8023c571d102bc7adce483d040348351/parser/clj_kondo/impl/rewrite_clj/node/quote.clj#L59-L77#2022-02-1303:50Sam Ritchie
(let [seq-node? (some-fn api/list-node? api/vector-node?)
        atom? (some-fn api/token-node? api/string-node? api/keyword-node?)
        tree (tree-seq seq-node? :children node)]
    (prn (remove (some-fn seq-node? atom?) tree)))
#2022-02-1303:51Sam Ritchiehere is my “isolate via exclusion” method 🙂#2022-02-1304:13Sam Ritchiepotential bug…
(even? ('a {'a 10}))
triggers an “Insufficient input” error… I’m not sure why, and I am convinced this is correct (the call evaluates)
#2022-02-1309:04borkdudeThis is a bug. You can ignore it with:
#_:clj-kondo/ignore
(even? ('a {'a 10}))
#2022-02-1306:30Sam RitchieHere is an example of a potential bug with :redundant-fn-wrapper:
(map (fn [x]
       {:pre [(odd? x)]}
       (- x))
     (range 10))
this triggers, but I would argue that it is NOT redundant because it adds a precondition. Thoughts?
#2022-02-1309:05borkdudeAlso a bug. Ignore it with:
#_:clj-kondo/ignore
(fn [x]
  {:pre [(odd? x)]}
  (- x))
Thanks for finding these!
#2022-02-1313:30Sam Ritchie@borkdude all 52k lines of tests + source from sicmutils linted, and all warnings and errors resolved! This project is amazing… I’m kicking myself for not enabling clj-kondo sooner. I’ll get an exact count when I polish the PR, but this process exposed a number of bugs that would have been damned hard to track down without the linter. Woohoo! Also I’m realizing that it’s such a pleasure to be able to write hooks that guide users toward correct usage of more difficult stuff like the pattern matching API. THANK YOU!#2022-02-1414:59Michaël SalihiHi, I experience a unresolved var on this line containing this p/-> macro despite the fact that I added promesa.core/-> clojure.core/-> in clj-kondo config: https://github.com/babashka/nbb/blob/main/examples/node-fetch/example.cljs#L20 Any idea?#2022-02-1415:03borkdude@admin055 you need to upgrade promesa in the deps.edn of your project, if you have any, since that's where clj-kondo will get the info from#2022-02-1415:04borkdudeor are you talking about editing files in the nbb repo itself?#2022-02-1415:06Michaël SalihiYes the second one...in the nbb repo so deps.edn already contains the last promesa version.#2022-02-1415:07borkdudeWhat editor are you using and how did you set up clj-kondo with it?#2022-02-1415:07borkdudeYou may need to restart your editor to trigger linting deps#2022-02-1415:08Michaël SalihiEmacs + LSP but I get the same warning when launching in CLI:
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "75181c1e10350507100601141b16101110061c121b"}, :content ("[email protected]")}
#2022-02-1415:09borkdudeRestart your workspace with lsp-workspace-restart#2022-02-1415:09borkdudeand then wait#2022-02-1415:09borkdudeand then make an edit#2022-02-1415:10Michaël SalihiAlready tested without success, I retry tho.#2022-02-1415:11borkdudeI'll also test locally#2022-02-1415:12Michaël SalihiThanks.#2022-02-1415:13Michaël Salihilsp will always align to messages obtained by clj-kondo on the command line, right?#2022-02-1415:14borkdudelsp might be using a slightly older or newer version than you have on the clj-kondo, but in 99% of the cases yes.#2022-02-1415:15borkdudeHmm, removing .clj-kondo/.cache and then doing lsp-workspace-restart fixed it for me#2022-02-1415:16borkdudebut then again, now it doesn't report any unresolved var when I type a wrong one#2022-02-1415:17borkdudeHmm, this is weird, when I do a manual:
$ clj-kondo --lint $(clojure -Spath) --dependencies
Downloading: funcool/promesa/6.1.434/promesa-6.1.434.pom from clojars
Downloading: funcool/promesa/6.1.434/promesa-6.1.434.jar from clojars
#2022-02-1415:17borkdudethen it downloads promesa newer for the first time. I don't know what lsp was analyzing here ...#2022-02-1415:18Michaël SalihiAfter delete the cache folder, it's solved. 👍#2022-02-1415:18borkdude@UKFSJSM38 this is a mystery to me. could you try this one the nbb project when you have time?#2022-02-1415:19borkdude@admin055 yeah, but you probably have the same problem as I have here: > but then again, now it doesn't report any unresolved var when I type a wrong one#2022-02-1415:19Michaël SalihiI try#2022-02-1415:22Michaël SalihiNo it works for me.#2022-02-1415:23borkdudeThat's not testing what I said :) Type p/foo#2022-02-1415:23borkdudeunresolved var != unresolved symbol#2022-02-1415:23borkdudeunresolved var = var from other namespace#2022-02-1415:23Michaël Salihioh sorry, misreading 🙂#2022-02-1415:24borkdudeIt's confusing, I know#2022-02-1415:24borkdudeI don't think lsp analyzes any dependencies anymore now#2022-02-1415:25borkdudeit's done in 1 or 2 seconds which is suspiciously fast#2022-02-1415:25Michaël SalihiYes indeed, I experience the same bug.#2022-02-1415:26Michaël SalihiDirectly with CLI clj-kondo too.#2022-02-1415:26borkdudebecause you haven't linted deps, that's expected. but normally lsp takes care of that#2022-02-1415:27borkdudeafter deleting .lsp/.cache and .clj-kondo/.cache and then an lsp-workspace-restart it started working again for me#2022-02-1415:29Michaël Salihi> because you haven't linted deps, that's expected. but normally lsp takes care of that OK understand. That's why you use clj-kondo --lint $(clojure -Spath) --dependencies before#2022-02-1415:29borkdudeindeed#2022-02-1415:29borkdudethat's what lsp is normally doing too#2022-02-1415:30Michaël SalihiInteresting...#2022-02-1415:30borkdudeunless it caches stuff, and caching as we all know is hard#2022-02-1415:30ericdalloThere is a bug on latest release regarding classpath cache, not sure it's the problem here, but it may worth try the latest master build from #clojure-lsp-builds#2022-02-1415:31Michaël SalihiPerfect, thanks for the information. Will try later. 👍#2022-02-1415:31ericdalloIt was a bug regarding a huge refactor I did about splitting cli from lib#2022-02-1415:31ericdalloI fixed couple days ago#2022-02-1415:32borkdudeBig refactors are sometimes worth it but can also be risky. That's why I hope y'all will try out babashka master before release 😰#2022-02-1415:33ericdalloHahha yeah, one of the reasons I created #clojure-lsp-builds as well I'm trying to avoid big refractors as well, but that one was on backlog for some months already#2022-02-1415:33borkdude#babashka-circleci-builds <--
$ bash <(curl ) --version 0.7.5-SNAPSHOT --dir .
$ ./bb
#2022-02-1415:33borkdudeThis refactor was on the list for 2 years or so ;)#2022-02-1415:40Michaël SalihiThanks both for the support! gratitude#2022-02-1421:00Sam Ritchieare there strong feelings on naming conventions for hook namespaces? I see a few options around, and want to make sure I am properly namespacing here#2022-02-1421:00Sam Ritchiehooks.sicmutils.namespace-where-the-macro-lives seems like a nice option#2022-02-1421:19borkdudeas long as the namespace name is unique and starts with or contains your org / lib name to avoid conflicts, it should be good#2022-02-1421:22Sam Ritchienice, I went with the convention above, thanks!#2022-02-1421:34Sam Ritchiethis seems to work, for linting multiple directories - clj-kondo --lint src --lint test . is this the recommended way? I’m setting up a Github Action with https://rymndhng.github.io/2020/04/03/Integrate-clj-kondo-with-Github-Actions/#2022-02-1421:35borkdude@sritchie09 You can do it like this as well: --lint src:test (classpath style, on Windows, use semicolon as path delimiter), or even --lint src test#2022-02-1421:51Sam Ritchienice. I am going to make CI fail on warnings, hardcore lifestyle#2022-02-1421:52Sam Ritchie#2022-02-1421:52Sam Ritchieawesome!!#2022-02-1423:07ghadigolang might be your jam#2022-02-1423:07ghadipersonally I think failing on unused bindings is too hardcore#2022-02-1423:24Sam RitchieOh boy, good point, maybe it's time to relax. If golang becomes my jam I'm switching fields… Recent conversion has my zeal fired up high#2022-02-1423:49Noah BogartI’m all for failing in unused vars #2022-02-1502:47lreadI like failing my builds on lint warnings too. Keeps things nice and tidy, yeah?#2022-02-1516:39Sam RitchieI am getting pretty fancy over here with api/reg-finding! to throw specific linter warnings for my pattern-matching DSL#2022-02-1516:40Sam Ritchiethere are some confusing rules for (pattern (+ (? x odd?) ?y ?z)), and the linter can sort of… teach the user what to do as they type. “x must be a non-namespaced symbol”, etc, so awesome.#2022-02-1516:40borkdude:)#2022-02-1516:41Sam Ritchiekind of makes me want to revive https://github.com/nathanmarz/cascalog… I have had thoughts over the years of writing it up as a literate program, would be fun to have a linter for the datalog syntax too#2022-02-1516:47borkdude@sritchie09 clj-kondo already has linting built-in for datalog as well, via the datalog-parser library#2022-02-1516:55Sam Ritchie@borkdude any chance I can beg for unquote? and friends to be exposed in the hooks API?#2022-02-1516:56borkdudesure, but you can probably already do this by doing (:tag node) right?#2022-02-1516:57Sam Ritchiewhoops, yes 🙂#2022-02-1517:24Sam Ritchie@borkdude should I rely on the fact that hook namespaces can require each other, or is that an accidental feature?#2022-02-1518:15borkdude@sritchie09 it's a feature.#2022-02-1519:30Stefan TI have to say, figuring out how to configure hooks has really filled in the gaps and eliminated most of the remaining false positives I used to have, great stuff! I was wondering, let’s say I have a couple dozen or so variations of a very similar macro that I would like to use the same hook for, is there any way I can avoid listing out every one of those in :analyze-call? Is it possible to configure :analyze-call with a function instead of a map?#2022-02-1521:03borkdude@stefan.toubia currently not possible#2022-02-1521:11borkdudeyou could of course just programmatically generate that map once :)#2022-02-1521:36Stefan TGotcha, thanks. In my case I have a handful of common macros generally used for testing, each project defines their own version but they all follow the same naming convention. It would be great to be able to just match the macro name, and avoid having to update the config when new macros are added. Will have to explore options for generating the config. Thanks for the advice!#2022-02-1521:37borkdude@stefan.toubia This might also come in handy if you want to update the config programmatically: https://github.com/borkdude/rewrite-edn#2022-02-1521:38Stefan TThanks! I will give it a try!#2022-03-0816:27Stefan THey @borkdude are there any options for maintaining/enforcing alphabetical ordering in a map when using rewrite-edn?#2022-03-0816:30borkdudethere's not a thing for it right now#2022-03-0816:30Stefan TAh darn, thanks.#2022-02-1521:37Sam Ritchie@borkdude is it possible to use a :clj-kondo/ignore to ignore the custom errors registered by my library? This does not seem to be working, for reference:
#_{:clj-kondo/ignore [:sicmutils.rule/ruleset-args]}
(ruleset (+ (? x) (? y)) (fn [m] (- ('?x m) ('?y m))))
#2022-02-1521:38Sam Ritchiemeaning, linting still gives that error:
[
#2022-02-1521:38Sam RitchieI have it enabled in my exported config like this:
{:linters
 {:sicmutils.pattern/ruleset-args {:level :error}}}
#2022-02-1521:43Sam RitchieI also can’t seem to override it in the :linters key of my project-local config.edn; and if I erase the entry from my exported config, I can’t enable it by adding
:sicmutils.pattern/ruleset-args {:level :error}
to my local config.edn
#2022-02-1522:03borkdudeNormally this should work. Not sure why it doesn't in this case. If you could make a small repro, then I'll investigate.#2022-02-1522:03borkdudeOr, I guess simcutils is already the repro.#2022-02-1522:04borkdudePost an issue with some details then please.#2022-02-1522:10Sam Ritchiesounds good!#2022-02-1522:15Sam Ritchie@borkdude is a repro in a sicmutils branch okay?#2022-02-1522:24borkdudeyeah, as long as I can reproduce it locally. the less deep I have to dig, the better it is of course#2022-02-1522:30Sam Ritchiehttps://github.com/clj-kondo/clj-kondo/issues/1586#2022-02-1522:31Sam Ritchie@borkdude hopefully this is an easy repro; I expect there is nothing sicmutils specific about this, but setting up a repro project is still fiddly. So hopefully this will work. let me know if it’s annoying and I can get a smaller one together#2022-02-1522:31borkdudethanks, I'll look later this week#2022-02-1522:35Sam Ritchiesg, thanks again#2022-02-1521:53Sam Ritchiephew, this hook got a bit turbo. Might be fun reading for anyone interested: https://github.com/sicmutils/sicmutils/blob/961b5bce04a03f1b41e5a39ab427d3a649a710b0/resources/clj-kondo.exports/sicmutils/sicmutils/hooks/pattern/rule.clj pretty cool given that this basically lints a different programming language embedded in clj#2022-02-1522:06borkdude@sritchie09 When you're done, please post a link here: https://github.com/clj-kondo/clj-kondo/discussions/1528#2022-02-1522:20Sam RitchieDone! https://github.com/clj-kondo/clj-kondo/discussions/1528 copied your style for descriptions of my custom linter warnings: https://github.com/sicmutils/sicmutils/blob/main/doc/linters.md#2022-02-1522:21borkdudeawesome!#2022-02-1613:30lreadJust an idea, not sure if it is a good one: I don't know how many times I've seen @seancorfield remind folks that clj-time is deprecated. I wonder if clj-kondo should/could warn on direct use of libraries that have been clearly documented as deprecated (except maybe not via :deprecated metadata). Some sort of ns list maybe?#2022-02-1613:32borkdude@lee I think that's an excellent idea and I assume @seancorfield would agree#2022-02-1613:33lreadHa! Coolio, I will make a git issue.#2022-02-1613:41imreWould be a good idea to add some documentation to reported failures on those. For example a link to an official-like statement or warning etc.#2022-02-1613:43borkdudelibraries could include this in their own exported clj-kondo config, that seems like the most authoritative statement#2022-02-1613:46borkdude@lee there is maybe already a related issue for deprecated namespaces. if a library as whole is deprecated, perhaps they can mark all of their API namespaces as deprecated and users would see it that way#2022-02-1613:48seancorfieldYes, I would love to see clj-time flagged as deprecated in code and in deps.edn (as both clj-time/clj-time and as just clj-time -- not sure whether clj-kondo canonicalizes libs?). depstar should also get flagged in deps.edn with a recommendation to use tools.build 🙂#2022-02-1613:49seancorfield(for the latter, you'd have to check for seancorfield/depstar, com.github.seancorfield/depstar, possibly io.github.seancorfield/depstar, and also com.healthfinch/depstar so I'm not sure how you'd want to handle that?)#2022-02-1613:51borkdudewell, doing it via the namespace metadata would be way easier, since that's what's clj-kondo is analyzing anyway and there would be no special rules inside clj-kondo needed for that#2022-02-1613:51lreadOh I didn't realize clj-kondo did not already warn on deprecated nses, https://github.com/clj-kondo/clj-kondo/issues/1125.#2022-02-1613:52borkdude
(ns depstar
  {:deprecated "use tools.build instead"})
  ^ Namespace depstar is deprecated: use tools.build instead 
#2022-02-1613:53lreadThought: That would help folks not to use the latest version of depstar, but the deprecation applies to all versions of depstar.#2022-02-1613:54borkdudetrue...#2022-02-1613:56lreadI think I'll raise the issue describing the problem, I'll link to the deprecated ns issue as related.#2022-02-1614:01seancorfieldIf a library is archived on GH, it's not going to get updates to add deprecation metadata 😉#2022-02-1614:02borkdudeok, so adding out of band information to a built-in config seems the way to go then.#2022-02-1614:07borkdudeand I guess we could add out-of-band information about deprecated namespaces inside of those libs as well#2022-02-1614:08borkdudewhile also supporting deprecated namespace data, so someone can add that information before archival#2022-02-1614:08seancorfieldDo you lint project.clj files?#2022-02-1614:08borkdudeno#2022-02-1614:09seancorfieldJust thinking that if you're going to start flagging libs in deps.edn you could also do that for project.clj 🙂#2022-02-1614:10borkdudemakes sense, since a lot of usage of those deprecated libs are still on project.clj#2022-02-1614:29lreadHere is the issue: https://github.com/clj-kondo/clj-kondo/issues/1591#2022-02-1614:30lreadMentioned antq might be an interesting partner in this crusade#2022-02-1716:22AkizHi, I am using clj-kondo/analysis and I would like to see the specific part of analysed source code. Let’s say there is (-> analysis :var-definition first) which returns
{:filename "/tmp/foo.clj",
                    :row 8,
                    :col 1,
                    :end-row 9,
                    :end-col 11,
                    :ns foo,
                    :name f,
                    :defined-by 'clojure.core/defn-
                    :private true,
                    :fixed-arities #{1}}
What would be the way to get the source code of this definition?
#2022-02-1716:23borkdude@zikajk Probably read /tmp/foo.clj at line 8 until line 9 and cut out the right columns#2022-02-1716:24borkdudeprobably just the lines will be enough for var defs#2022-02-1716:27Akiz@borkdude Cool, this works for me. I wanted to be sure that i dont reinvent wheel. thanks again.#2022-02-1914:19eccentric JDrafting p/try and p/catch for promesa.I've configured :lint-as so that kitchen-async.promise/try and catch match the clojure core counterparts but it seems like kondo is checking for catch and not (p/catch) which is resulting in that lint error. Is that fixable somewhere along the way or perhaps is this a non-starter?#2022-02-1915:52eccentric J@U04V15CAJ Thoughts on this ^ Want to know if it's worth solving or if it's a can of worms for tools like kondo#2022-02-1915:53borkdude@U8WFYMFRU p/catch already exists in promesa. how would you re-use it for this macro?#2022-02-1915:55eccentric JIn kitchen-async they introduce a separate name (which was going to be my strategy too) . The way they set it up was that there was p/catch for p/try and p/catch* for promise.catch. Was thinking on reversing that so promesa.catch* would be the counterpart to promesa.try. But it seems like getting p/try working and using lint-as might create more problems given that kondo is throwing an error that there is no catch statement in there#2022-02-1915:56eccentric J#2022-02-1915:57eccentric JSo if it's not too much trouble in kondo (willing to help with the PR) then I'll continue with the promesa PR, but if it just creates more problems then it may not be worth implementing#2022-02-1915:58borkdudethere's always a way to support this in clj-kondo via hooks#2022-02-1915:58borkdudeit even has support for better-cond via custom hooks which is quite complicated#2022-02-1915:58borkdudeso there's no reason to restrain yourself here#2022-02-1915:59eccentric JI see so I can start out with using hooks in my userland config, then can include it in the promesa config when I'm ready for that upstream PR?#2022-02-1916:00borkdudeyeah#2022-02-1916:00eccentric JThat works, thanks once again for your insight!#2022-02-1916:45lreadI started https://github.com/clj-kondo/clj-kondo/discussions/1593. All with an interest and/or opinions are most welcome.#2022-02-2114:12ericdalloI noticed something that I'm not sure it's a bug or something to be improved 🧵#2022-02-2114:15ericdalloAt Nubank we noticed that thrown? was being warned as :unresolved-symbol in a project, after a lot of debugging and unnecessary cache cleaning 😂 we found that when you add a custom exclude config of a linter, clj-kondo stop considering its global config, in this case the global config for thrown? https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/config.clj#L57, so we needed to include this manually on our config which most users probably won't expect that right?#2022-02-2114:16ericdallomaybe we should have a merge of excludes taking precedence the inputted by user#2022-02-2114:17ericdallowe had this at our config:
:linters {:unresolved-symbol {:exclude #{a-custom-function}}}
#2022-02-2114:17ericdalloif we remove this exclude, the thrown? started to work again#2022-02-2114:30borkdudeyou should use a vector there#2022-02-2114:30borkdudethat's probably the issue#2022-02-2114:31borkdudethese things are already merged normally, if you use the vector notation#2022-02-2114:32borkdudehttps://github.com/clj-kondo/clj-kondo/blob/4495e9387733e891ee735d745fd0bcf92185d59c/src/clj_kondo/impl/utils.clj#L147#2022-02-2114:32borkdudesequential is appended to sequential#2022-02-2114:32ericdallo🤯 good to know#2022-02-2114:32borkdudeset + set is joined as set#2022-02-2114:32borkdudeset + vector is undefined, but could probably also do into there#2022-02-2114:33ericdalloyes, agreed#2022-02-2114:33ericdalloeven so, I'll change to vector, thank you!#2022-02-2123:06wilkerluciohello, I notice something with the auto-include feature in kondo, seems like it requires that the library has 2 segments (directories) to pick up, in the case of Promesa which has a single one, it does auto import, but doesn't auto load it, is this expected?#2022-02-2123:07borkdudeyes, the config should have two segments#2022-02-2123:08borkdudein the case of promesa, that would probably be: funcool/promesa#2022-02-2123:09borkdudeAnother reason why it didn't work yesterday @U8WFYMFRU#2022-02-2123:11eccentric JAh so should have renamed the .clj-kondo/promesa dir to clj-kondo/funcool/promesa?#2022-02-2123:12borkdudepromesa should have done this, but you can fix it locally like that yes#2022-02-2123:14eccentric JCool will try that, thought it was working but turned out to just be a delay before raising errors. Ended up going back to local config.edn lint-as, will try it again and try renaming it.#2022-02-2123:15wilkerluciosorry about that, was my fault, I sent it there and missed the segment#2022-02-2123:15wilkerlucioPR to fix is up: https://github.com/funcool/promesa/pull/101#2022-02-2123:19eccentric JAll good, thank you!#2022-02-2123:10borkdude@wilkerlucio Thanks for adding that config, hope that can be fixed in promesa.#2022-02-2123:13wilkerlucioI'm just sending the fixes to them right now 😉#2022-02-2123:15wilkerluciohttps://github.com/funcool/promesa/pull/101#2022-02-2211:14Jacob EmckenI am getting an "unresolved symbol" error from a custom macro and was trying to solve it using the example from the documentation about (riemann.streams/streams [where]) At the risk of over simplifying my problem, I want to be able to call my macro with any name, like so:
(custom-macros/with-dinner water blueberry-pie
  ...
Is it possible to individual names from usage to usage and not being limited to be using only generics drinks and food everywhere? But I am also not interested in just ignoring everything inside the macro.
#2022-02-2212:03borkdude@jacob429 I think a better option is to write a hook for this macro. This allows you to have finer control over how the macroexpansion in clj-kondo should behave#2022-02-2216:20Jacob EmckenThanks, 🙂 I'll look into hooks then#2022-02-2212:10borkdude@jacob429 Another option is to put #_:clj-kondo/ignore directly before the unresolved symbol#2022-02-2316:47martinklepschFor cljc files is there a way to not lint the Clojure side of things and instead only lint ClojureScript?#2022-02-2316:48martinklepschAsking because with shadow-cljs it’s somewhat common to use #?(:browser ..) and node reader conditionals#2022-02-2316:48martinklepschand you don’t really want to lint the namespace as Clojure#2022-02-2316:49borkdudeYes, but undocumented since I was unsure about the API. Try:
{:cljc {:features #{:cljs}}}
#2022-02-2318:03alexIf we adopt the above config, what is the recommended approach for linting the Clojure branch in some .cljc files but not others? Most of our .cljc files are Clojurescript only, but there are a handful that expose implementations for both Clj and Cljs After implementing the :cljc config above, I'm seeing that clj-kondo reports "Unresolved var" wherever a Clojure namespace consumes a var defined in a .cljc file For example,
;; log.cljc

(defn info
  [& s]
  (let [msg (fmt s)]
    #?(:clj  (log/info msg)
       :cljs (glog/info logger msg))))

;; user.clj

(log/info (str "Rendering CSS to " path))
;; clj-kondo reports unresolved var log/info
#2022-02-2318:06alexI tried adding a {:clj-kondo/config '{:cljc {:features #{:clj :cljs}}}} override in the log.cljc namespace declaration, but that didn't seem to work#2022-02-2318:52borkdudeThat doesn't work yet, since by the time clj-kondo reads that config, the cljc branches have already been parsed#2022-02-2318:53borkdudeThe unresolved var is because clj-kondo is only going to analyze the features you specify. The intention of that config is to disable .cljs completely for babashka projects that use .cljc files#2022-02-2319:28alexAh got it, so right now it's an all-or-nothing type of deal with the :cljc config Hmm, given the situation described in our use case above, do you any suggestions on a way to make this work?#2022-02-2319:45borkdudeCurrently not#2022-02-2319:59alexThanks! That is our lone Clojure namespace, and it's rarely updated, so maybe we can just get away with not linting it... 😬#2022-02-2320:04borkdudeMaybe you can explain what your issue is with this, since this requirement has never come up before#2022-02-2320:05borkdudeIf it's your only clojure namespace then I don't see why you wouldn't use the global config#2022-02-2320:30alexAh sure - thanks for working through it with me. My issue is an extension of what Martin wrote above We have lots of .cljs files, ~20 .cljc files, and a single .clj file. The .cljs files are used in both Node and browser for server and client-side rendering We have 2 distinct sets of .cljc files: • those that target :node and :browser ; shadow-cljs supports using the reader conditional to target different JS platforms e.g. node and browser to consume specific platform-specific APIs. These import other CLJS namespaces • those that target :clj and :cljs And we have a single .clj file that imports a couple .cljc namespaces --- Without the :cljc {:features #{:cljs}} config you shared above, we would have to wrap most of the .cljc namespaces (required imports and vars) in #?(:cljs) to prevent the Clojure path from being linted. Ideally we would be able to just use the #?(:browser) reader conditional on the leaf nodes where we utilize the browser-specific API e.g. js/window or js/document#2022-02-2320:37alexIs your suggestion to use the global config to ignore the unresolved var errors for Clojure files?#2022-02-2320:38borkdudeWith global I meant :cljc {:features #{:cljs}} which I think makes sense for your project. And then you could maybe just ignore the one .clj file or put a namespace config in that one.#2022-02-2320:38borkdudeOr perhaps I'm still missing what the issue is.#2022-02-2320:40alexYep, utilizing the :cljc config + ignoring the one .clj file was what I had in mind 🙂 Thanks!#2022-02-2402:16Drew Verleewould there be a way to use clj-kondo to read clojure and sort of expand regular clojure the same way you do macro expand? Like (defn foo [x] x) (defn bar [x] (foo x)) -> expand "(foo x)" -> (defn bar [x] x)#2022-02-2411:02delaguardocool, idea. something like "term rewrite" but in clojure such analyser have to take in account that foo is not static value, it is a reference that can be redefined in runtime#2022-02-2415:23StefanHi all! I just had a situation that caught me off guard. I had a test that should fail, but didn’t when running the tests from the command line (poly test in my case). The reason turned out to be that the namespace name of the test file did not match the file name. I was surprised that clj-kondo didn’t catch this. Do you think this would be a good linter to add to clj-kondo? I.e.: check whether the namespace name matches the filename + path of the file?#2022-02-2415:25borkdude@stefan.van.den.oord Absolutely and there is already an issue for it. It might be a relatively easy one if you want to hack on it. https://github.com/clj-kondo/clj-kondo/issues/1240#2022-02-2415:26StefanCool, I will definitely keep that in mind. I think I might pick that up quite soon.#2022-02-2416:20Stefan@U04V15CAJ Could you jump-start me by telling roughly where I should add my code?#2022-02-2416:22borkdudeSomewhere here: https://github.com/clj-kondo/clj-kondo/blob/4495e9387733e891ee735d745fd0bcf92185d59c/src/clj_kondo/impl/analyzer/namespace.clj#L358 In the ctx is a key called :file that you can use to compare to the name of the namespace#2022-02-2416:22borkdudeAlso read this https://github.com/clj-kondo/clj-kondo/blob/master/doc/dev.md#2022-02-2416:30StefanFor the unit test I think it would be easiest to create a couple of test resource files that I then read in in the unit test, is that ok with you? (Just checking because this way of testing by reading actual files doesn’t seem to be used yet.)#2022-02-2416:31borkdudeyes, there is a directory called "corpus" for this#2022-02-2416:32StefanA right I just found that, sorry for asking too quickly.#2022-02-2416:32borkdudeno problem#2022-02-2421:16borkdude@stefan.van.den.oord you can disable the linter for all of the other tests in test_utils#2022-02-2421:17borkdudehttps://github.com/clj-kondo/clj-kondo/blob/4495e9387733e891ee735d745fd0bcf92185d59c/test/clj_kondo/test_utils.clj#L80#2022-02-2421:25StefanYeah thanks, that’s indeed the strategy that I’m working on 🙂 I didn’t know about the base config there, that’s going to make it a lot easier, thanks! 🙂#2022-02-2421:25StefanHow should it behave (in real-life) when there are multiple ns-forms in a file?#2022-02-2421:34StefanCurrently it will report the ones that don’t match the file name. I think that’s desired behaviour, do you agree @U04V15CAJ?#2022-02-2421:41borkdudeNot sure#2022-02-2421:42borkdudePerhaps just take the first one?#2022-02-2421:42StefanThat does make the linter more complex of course. I’m not sure what the use case would be for this. You can always silence the warnings with comments in the file…#2022-02-2421:46StefanI’m calling it the day. 🛏️ There’s a few failing tests remaining that I have to look into, I will followup soon.#2022-02-2421:52StefanRe multiple ns forms: the question is I think: in cases where this occurs in real life, is it by accident or on purpose most of the time? I have never felt the need to have multiple ns forms in one file.#2022-02-2421:53borkdudeOk, then why the question? Did this come up in the tests?#2022-02-2421:54StefanI saw it in corpus/use.clj.#2022-02-2421:56StefanNot after disabling my linter in base test setup of course, but that’s why it made me think.#2022-02-2421:58borkdudeyeah, ok. I think it's ok to just keep it simple and lint it always#2022-02-2421:58borkdudewe can change it when we need to.#2022-02-2422:03StefanNow locally all tests are passing, but not in CI. Not sure what’s going on. But that will have to wait till tomorrow. Good night!#2022-02-2422:03borkdudeGood night!#2022-02-2508:07StefanTests are green! 🎉 https://github.com/clj-kondo/clj-kondo/pull/1596#2022-02-2420:27borkdude@grzegorz.rynkowski
(->> '("Mike" "Tom" "Jerry")
     (map (fn [x] (count x)))
     (cond->> true (map str)))
gives the same warning to me, so your lint-as seems to be working :)
#2022-02-2420:29gregOh, right, cond->> might not be a good linter for ?>>. Nope, I did not 😬#2022-02-2420:30borkdudeThe example doesn't run, but throws an exception#2022-02-2420:32gregsorry @U04V15CAJ, I was too eager and added a unnecessary lint-as statements for ?>>. There is no issue. Sorry.#2022-02-2420:47borkdudeNo problem#2022-02-2420:27borkdudeHave you tried executing that example?#2022-02-2420:29danielcomptonFor exported config (in our case marick/midge/config.edn) is it expected that we would add this to source control or gitignore it and let each user's computer generate it for them?#2022-02-2420:30borkdude@danielcompton I prefer to check it into source control so everyone has the same consistent linting results#2022-02-2420:30borkdudealso when you don't scan your classpath in a clean checkout#2022-02-2510:47borkdude@stefan.van.den.oord is working on a namespace linter that warns when the name of the ns does not match the filename. But for scripts (clojure and babashka) it is fine to use normal dashes in the name. So foo-bar.clj and (ns foo-bar) is fine for scripts that you invoke directly with bb foo-bar.clj, but not for files on the classpath. Any suggestions on how to deal with this? Maybe a heuristic that when there is no "src" or "test" in the parent segments, the file isn't on the classpath and can be assumed a script?#2022-02-2510:51StefanWould it make sense to have a different set of default linter configs for that type of use? In other words, invoking clj-kondo slightly differently so that it knows it is running in “scripting mode” and then have different defaults?#2022-02-2510:52borkdudeNo, if you are using clj-kondo in your editor you don't invoke it yourself and that's the primary mode of usage as far as I'm concerned#2022-02-2510:54borkdudePeople could just use #_:clj-kondo/ignore in this case or just adopt the convention to use underscores in their script file names perhaps.#2022-02-2510:55borkdudeMight be worth making a test case to see if the ignore annotation works correctly with this linter#2022-02-2510:56borkdudeChecking for the presence of a shebang could also work#2022-02-2510:59Stefanshebang is not always present in scripting mode I think.
cat some-text-file-containing-clojure.clj | bb
#2022-02-2511:00borkdudeIn your example using a namespace form is pretty unusual.#2022-02-2511:00StefanExample updated 🙂#2022-02-2511:00borkdudeYou're right that a shebang isn't always present, but that would be a way for people to get rid of the warning#2022-02-2511:01StefanThat feels a bit like magic to me…#2022-02-2511:01borkdudeBut maybe we could let it be for now and just let people use the ignore annotation#2022-02-2511:01borkdudeSo please add a test for that one#2022-02-2511:04StefanYes good idea.#2022-02-2514:47Noah Bogarti'm writing a hook. what's the best way to debug it?#2022-02-2514:49Alex Miller (Clojure team)I read that as "writing a book" and laughed#2022-02-2514:49imreI was asking the same a while back, check out this thread https://clojurians.slack.com/archives/CHY97NXE2/p1644324979611669#2022-02-2515:30Noah Bogarta combination of --debug and with-in-str nailed it. thanks so much!#2022-02-2517:40Noah Bogartto follow up, I have a macro that creates a private function and then binds the function to public atom, which allows for repl-based testing while keeping the in-code usage through the atom. is it possible to output the {:node node} in my :analyze-call hook that ignores the unused-private-var warning?#2022-02-2517:50Noah Bogart~oh wait, this is a clojure-lsp issue, i'll work from there.~ never mind, this is in fact a clj-kondo issue. any ideas on how to fix this?#2022-02-2518:30borkdude@nbtheduke Just use the unused private var once in your hook, that will take care of the warning, e.g. (let [_ private-var])#2022-02-2518:34Noah Bogartmind if i PM you about this? i don't want to share the code publicly but i'm unsure how to do that with the code i have written#2022-02-2518:35borkdudeok#2022-02-2615:22Noah Bogart@borkdude how would you feel about adding this as a lint? If interested, I could try writing it up#2022-02-2615:24borkdude@nbtheduke I've been on a team which consistently used keyword style destructuring. I wouldn't want to inflict dozens of new unnecessary lint warnings on them ;).#2022-02-2615:56Darin Douglass#2022-02-2615:59imreOff by default?#2022-02-2615:59borkdudeWe could do that#2022-02-2616:58Noah BogartI'll open an issue with my thoughts and see what I can cobble together in a small pr#2022-02-2617:34dharriganI think it makes a good lint, with off being the default - so as not to upset anyone 🙂#2022-02-2800:48pfeodrippeI use symbols on my daily job (because it was already like that), but keywords in my personal projects. I didn't want to know it was a workaround, my life is a lie. One reason for keywords is that grep just works, no need to rely on any external tooling, but nowadays the tooling is just there that I don't know if it's a valid reason anymore. Anyway
{:keys [:deal-with-it]}
#2022-02-2818:32pithyless@nbtheduke I think it's only fair to also provide an optional linter that does the reverse: catch any :keys that are using symbol bindings instead of keywords. I feel seen by @U02EA2T7FEH - I am one of the dozens.#2022-03-0110:14Israel GerbiHey @borkdude! A question about disabling specific linter / file I have a file named unleash_client.clj with a public method called enabled? Currently, all usages of this method are removed though I get the following error when running lein lint:
=================== WARNING: Parents ======================
==    Could not find any references to the following     ==
===========================================================

af-wh-engmnt.utils.unleash-client/enabled?

================== WARNING: Children ======================
==   The following have references to them, but their    ==
==   parents do not.                                     ==
===========================================================

af-wh-engmnt.utils.unleash-client/get-context
Subprocess failed
I have tried to disable this warning for this specific file / method in a few ways using the https://cljdoc.org/d/clj-kondo/clj-kondo/2020.02.15/doc/configuration, nothing worked Any ideas?
#2022-03-0110:15Israel Gerbimy last attempt of the .clj-kondo/config.edn file:
{:linters {:unresolved-symbol {:exclude [(clojure.core.match/match)
                                         (compojure.core/routes)
                                         (net.cgrand.enlive-html/deftemplate)
                                         (manifold.deferred/let-flow')
                                         (mount.core/defstate)]
                               :level :info}
           :unused-referred-var {:level :warning
                                 :exclude {taoensso.timbre [info spy debug error warn]}}
           :unused-binding {:exclude-destructured-keys-in-fn-args true
                            :level :warning}
           :unused-namespace {:exclude [taoensso.timbre]
                              :level   :off}
           :invalid-arity {:skip-args [clojure.core.match/match]}
           :consistent-alias {:level   :warning
                              :aliases {clojure.string string
                                        clojure.set set
                                        clojure.walk walk
                                        af-wh-engmnt.utils.json json}}}
 :output {:exclude-files ["src/af_wh_engmnt/utils/unleash_client.clj"]}
 :skip-comments true
 :lint-as {mount.core/defstate clojure.core/def}}
#2022-03-0110:19borkdudeI do not recognize those warnings as something that comes from clj-kondo
#2022-03-0110:19borkdudeIf you can provide a full standalone repro, I can take a look, but not with only the information you posted above.#2022-03-0111:13Israel Gerbisure I’ll provide one, thanks!#2022-03-0111:22Israel Gerbidoubled checked, you’re right, it doesn’t come from clj-kondo, rather than a library called https://github.com/venantius/yagni I’ll search for a solution there, thanks!#2022-03-0316:53jeroenvandijkI want to write a linter that does a different suggestion for System/currentTimeMillis and java.util.UUID/randomUUID . I was able to implement the first linter, but the second doesn’t seem to be recognized. I think because java.util.UUID is not part of https://github.com/clj-kondo/clj-kondo/blob/master/resources/clj_kondo/impl/java-info.edn Should I make an issue for this (and PR) or is it more complicated?#2022-03-0316:56borkdudeIssue welcome. I'm not sure what the right answer is, we could probably allow hooks for things clj-kondo doesn't know#2022-03-0712:08jeroenvandijk@U04V15CAJ I’ve created an issue here https://github.com/clj-kondo/clj-kondo/issues/1603#2022-03-0316:58jeroenvandijkThanks! Ok I’ll do this today or tomorrow#2022-03-0317:16borkdude@stefan.van.den.oord Thanks again for working on this namespace + file consistency linter, pretty helpful and found no further regressions#2022-03-0319:50StefanThanks @U04V15CAJ , my pleasure! It already helped me find two test namespaces that were not executed in our code base, I hope others are going to find it equally useful 😀#2022-03-0412:45orestisI'm looking to do some static analysis: collect all usages of foo.bar/translate , and collect the following information: 1. literal value of the first argument (e.g. if called like (t/t "Hello") I'd like to collect "Hello" 2. filename, line, column I'm looking at the clj-kondo analysis option and in the output file I can see row, col/`end-col` which means I can probably read the source file manually, skip to row and parse the Sexpr manually somehow. Am I missing something? Would I use something like edamame to safely parse the s-expression? (I guess clojure.edn could also work for 95% of the cases)...#2022-03-0412:47borkdude@orestis Is this for linting or just gathering information?#2022-03-0412:48orestisThis is only to gather information#2022-03-0412:49borkdudeI think you could do this using a hook. Just write a hook for your function, collect the first argument, call (api/reg-finding! (assoc (meta arg-node) :message "collect some info" :type :my-custom/linter)) and then register {:linters {:my-custom/linter {:level :info}}}#2022-03-0412:49orestis(Eventually we may write a custom linter if the approach holds, but for now we need to collect info)#2022-03-0412:50borkdudeand then call clj-kondo in the jvm and collect :type :my-custom/linter from the :findings#2022-03-0412:50borkdudeAn alternative without clj-kondo could be using https://github.com/borkdude/grasp#2022-03-0412:51borkdudeIf you're planning to add linting later, I'd go for the clj-kondo approach#2022-03-0412:53orestisCan I call clj-kondo with only this single linter?#2022-03-0412:54borkdude@orestis yes, {:linters ^:replace {:my-custom/linter {:level :info}}}#2022-03-0412:57orestisLooking into the hook#2022-03-0412:59borkdude@orestis example:
$ clj-kondo --lint code.clj --config .clj-kondo/find_hello.edn
code.clj:4:20: info: Hello

$ cat code.clj
(ns code
  (:require [foo.bar]))

(foo.bar/translate "Hello")

$ cat .clj-kondo/hooks/hello.clj
(ns hooks.hello
  (:require [clj-kondo.hooks-api :as api]))

(defn translate-hook [{:keys [node]}]
  (let [arg (second (:children node))]
    (when (= "Hello" (api/sexpr arg))
      (api/reg-finding! (assoc (meta arg)
                               :message "Hello"
                               :type :my-custom/linter)))))

$ cat .clj-kondo/find_hello.edn
{:linters ^:replace {:my-custom/linter {:level :info}}
 :hooks {:analyze-call {foo.bar/translate hooks.hello/translate-hook}}}
#2022-03-0413:10borkdude^ slightly adapted it @orestis#2022-03-0413:16orestisHm, I'm having trouble with the config. The file is getting linted with my main config...#2022-03-0413:17borkdudeSee example: `
--config .clj-kondo/find_hello.edn
#2022-03-0413:18orestisSorry, it gets linted with the new config in addition to the previous one. So I'm also getting warnings about unused requires etc.#2022-03-0413:18borkdudeSee ^:replace in the config#2022-03-0413:19orestisYep, it's there:
{:linters ^:replace {:nosco.i18n/translate {:level :info}}
 :hooks {:analyze-call {nosco.i18n.translate-server/t hooks/translate-server}}}
#2022-03-0413:19borkdudeAnd how are you calling it on the command line?#2022-03-0413:20orestis
clj-kondo --lint src/nosco/reports/ideas.clj --config .clj-kondo/i18n-config.edn
#2022-03-0413:20orestisClearly the i18n-config.edn is picked up as the new linter doesn't exist in the base config.#2022-03-0413:21borkdudeAre you planning to use this in the JVM or the command line?#2022-03-0413:22orestisIdeally I'd invoke it via the JVM as then I wouldn't need to parse the text output.#2022-03-0413:22borkdudeclj-kondo supports outputting EDN and JSON as well btw#2022-03-0413:23borkdude
$ clj-kondo --lint code.clj --config .clj-kondo/find_hello.edn --config '{:output {:format :edn}}'
{:findings [{:row 4, :col 20, :end-row 4, :end-col 27, :message "Hello", :type :my-custom/linter, :filename "code.clj", :level :info}]}
#2022-03-0413:24orestisGood to know! In this case it doesn't really matter how does it get invoked - but it would be good to avoid other linters.#2022-03-0413:26borkdude
$ clj-kondo --lint code.clj --config .clj-kondo/find_hello.edn --config '{:output {:format :edn}}' | jet --func '#(->> % :findings (filter (comp #{:my-custom/linter} :type)))'
({:row 4, :col 20, :end-row 4, :end-col 27, :message "Hello", :type :my-custom/linter, :filename "code.clj", :level :info})
#2022-03-0413:26borkdude
#(->> % :findings (filter (comp #{:my-custom/linter} :type)))
#2022-03-0413:26borkdudeI think I would just use that as the ^:replace solution is pretty hard to get right#2022-03-0413:27orestisInteresting: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#disable-all-linters-but-one#2022-03-0413:28orestisIf I put the ^:replace on the outside of the map, I get this error WARNING: file hooks.clj not found while loading hook#2022-03-0413:28borkdudeyes, but that will disable your :hook config as well, so just don't use it#2022-03-0413:28orestisgotcha.#2022-03-0413:30orestisThanks for the guidance, this is promising. I will have to finish it some other time though#2022-03-0414:12orestisManaged to finish this, via invoking by the JVM#2022-03-0414:12orestisThanks for the guidance!#2022-03-0414:13borkdude:thumbsup:#2022-03-0414:34borkdude#2022-03-0415:58Sam Ritchie@borkdude for this issue https://github.com/sicmutils/sicmutils/pull/478, I wrote :kondo/ignore but the actual code correctly used :clj-kondo/ignore ;#2022-03-0416:00borkdudeCould not reproduce. Please make a standalone small repro and I'll try again.#2022-03-0416:00Sam Ritchiesounds good#2022-03-0416:20Sam Ritchie@borkdude https://github.com/sritchie/kondo-repro#2022-03-0416:21Sam Ritchierepro achieved. my issue with overriding the error in the config was wrong, that was my mistake. but the inline override still does not work, and reproduces here on my machine#2022-03-0416:31Sam RitchieEven a bare #_:clj-kondo/ignore seems to fail with my custom warning. You can see the linter triggering on the top form but not the bottom form:#2022-03-0417:06borkdudeThanks! I'll re-open the issue with your repro#2022-03-0420:09borkdudeFound the problem, reported in the issue.#2022-03-0420:24Sam Ritchieawesome, thank you! I responded too and took your recommendation for all linters exported by sicmutils.#2022-03-0717:52fabraoHello, I´m having this problem in clj-kondo and Calva
Can't parse /c:/Trabalho/Clientes/test/projeto/back-end/src/core.clj, Illegal char <:> at index 2: .c:.Trabalho.Clientes.test.projeto.back-end.src.core.cljclj-kondo
#2022-03-0717:53fabrao#2022-03-0717:54fabraoI saw this after an update#2022-03-0718:46borkdude@fabrao Can you file an issue + repro?#2022-03-0718:47fabraosure, it seems to be something about Windows problem#2022-03-0718:52borkdude@fabrao is possible, make a repro using clj-kondo on the command line
clojure -Sdeps '{:deps {clj-kondo/clj-kondo {:mvn/version "2022.03.04"}}}' -M -m clj-kondo.main --lint c:/foo.clj
#2022-03-0719:00borkdudeThis looks like it could have to do with the new namespace linter. @UGNFXV1FA#2022-03-0719:02borkdude@fabrao Does Calva print a clj-kondo version?#2022-03-0719:03borkdudeCan you also specify what you are using: Calva + clojure-lsp or the clj-kondo extension?#2022-03-0719:09fabrao#2022-03-0719:10fabraoPS C:\> clj-kondo --version clj-kondo v2021.12.16#2022-03-0719:11borkdudealright, thanks#2022-03-0719:11borkdudecan you try to make a repro with the updated clj-kondo on the command line too?#2022-03-0719:12StefanIs that also the version that Calva is using? Doesn’t it bundle its own instance of clj-kondo?#2022-03-0719:12borkdudeNo, it's using the standalone clj-kondo plugin it seems, which is the newest version. clojure-lsp isn't using the newest clj-kondo yet.#2022-03-0719:14Stefan@fabrao You could try disabling the :namespace-name-mismatch linter in your config, if that fixes it then it’s conclusive where the issue is. I’ll have a look at the source code but I didn’t think of paths including /c:/ so I’m not sure if that works.#2022-03-0719:14borkdudeDisabling that linter doesn't deactivate the code-path in which this error happens I think#2022-03-0719:14StefanOk right#2022-03-0719:14fabraoclj-kondo --version clj-kondo v2022.03.04 -> same result#2022-03-0719:15borkdude@fabrao can you please specify an exact repro on the command line, including the filename#2022-03-0719:15StefanBut if it’s going wrong with clj-kondo v2021.12.16 it must be something else…?#2022-03-0719:16borkdudeThis is why I'm asking for an exact command line repro. Please test with the old and new version.#2022-03-0719:18fabrao
PS C:\Windows\System32> clojure -Sdeps '{:deps {clj-kondo/clj-kondo {:mvn/version \"2022.03.04\"}}}' -M -m clj-kondo.main --lint c:/Trabalho/Clientes/test/projeto/back-end/src/core.clj
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding='UTF-8'
linting took 106ms, errors: 0, warnings: 0
#2022-03-0719:19fabraoso strange !!!#2022-03-0719:20borkdudeso on the command line it behaves correctly?#2022-03-0719:21fabrao
clj-kondo --lint c:/Trabalho/Clientes/test/projeto/back-end/src/core.clj
linting took 9ms, errors: 0, warnings: 0
#2022-03-0719:22fabraoyes, no problem with command line#2022-03-0719:23borkdudeok, please file an issue with the contents of the file and directory structure. Then I can try to reproduce using VSCode on Windows.#2022-03-0719:29borkdude@UGNFXV1FA I guess you don't have access to a Windows machine right?#2022-03-0719:30StefanNo. Maybe I could spin up a VM but it would take hours to get up and running. But the results above suggest it is unrelated to my PR, or am I misinterpreting?#2022-03-0719:31fabraoEven when Calva Repl is not running, the problem happen#2022-03-0719:31borkdude@fabrao can you downgrade the clj-kondo plugin to the previous version?#2022-03-0719:32borkdudethen we can be sure that it's not related to the new namespace linter...#2022-03-0719:32borkdudeclj-kondo does not use the Calva REPL#2022-03-0719:34borkdude@fabrao this is how you do that:#2022-03-0719:35fabraoJust to let you know, I tried with VSCODE + WSL 2 and no problem#2022-03-0719:35borkdude@UGNFXV1FA I'll take a look on my Windows machine, no problem#2022-03-0719:36fabrao#2022-03-0719:36borkdudeyes, it's definitely Windows related and the only thing that comes to mind is that new namespace linter since that looks at the filename#2022-03-0719:37fabraoWindows#2022-03-0719:38fabrao#2022-03-0719:39fabraoeven I installed with 2022.03.04 -> shows 2022.02.09#2022-03-0719:39borkdude@fabrao to pin down the issue, can you please disable Calva and only use the clj-kondo extension. you have installed the clj-kondo plugin from which this error comes.#2022-03-0719:40fabrao#2022-03-0719:41fabrao@U04V15CAJ you see, console is showing other version than installed#2022-03-0719:41borkdudethat console output comes from Calva, ignore it#2022-03-0719:41borkdudeand disable it#2022-03-0719:42borkdudeif you are using Calva you don't have to use the clj-kondo extension, since clojure-lsp already comes with clj-kondo included.#2022-03-0719:42fabraoI disabled Calva, and the same problem happen#2022-03-0719:42borkdudebut now that you have bumped into this issue, let's take advantage of this and get to the bottom of it#2022-03-0719:43borkdudeyes, as I said, this is coming form the clj-kondo extension. please try the older version 2022.2.9 now#2022-03-0719:45fabraowith older version, the problem gone#2022-03-0719:46fabraoI re-enabled Clava, and it´s going ok#2022-03-0719:47fabraowhat a mess VSCODE did !#2022-03-0719:47borkdudeyes, so it's likely that it is introduced in the latest version. thanks for checking#2022-03-0719:47borkdudeyou can uninstall the clj-kondo extension if you are using Calva#2022-03-0719:48borkdudecan you still make a Github issue for this?#2022-03-0719:48fabraoIt´s up to you#2022-03-0719:49fabraoI have to use clj-kondo because I have clj-kondo in git action, so I have check it out before PR#2022-03-0719:49borkdudeyes, but if you are using Calva, you get clj-kondo as well, automatically#2022-03-0719:50fabraook, I did´t know#2022-03-0719:50borkdude> It´s up to you Well, please do#2022-03-0719:51borkdudeThanks for discovering this problem before Calva/lsp updates clj-kondo though :)#2022-03-0719:51fabraoIf I didn´t use clj-kondo, I could not find the bug 🙂#2022-03-0719:51fabraoI'll keep it to help community#2022-03-0719:52borkdudethanks :)#2022-03-0719:59fabraohttps://github.com/clj-kondo/clj-kondo/issues/1605#2022-03-0720:01borkdudeCan you also specify the code in the file in the issue?#2022-03-0720:01borkdudeAnd also the full directory structure#2022-03-0720:01borkdudeso I can reproduce this locally#2022-03-0720:53borkdudeI think I've reproduced the problem:
user=> (fs/strip-ext ".c:.foo.bar")
java.nio.file.InvalidPathException: Illegal char <:> at index 2: .c:.foo.bar [at <repl>:7:1]
#2022-03-0721:11borkdudePushing a fix to branch issue-1605-windows-test#2022-03-0722:34borkdudefixed on master#2022-03-0722:34borkdudewill do a release tomorrow#2022-03-0808:48borkdudeReleased and works in VSCode now#2022-03-0811:48borkdudeFfffk, there is another problem on Windows#2022-03-0811:48borkdudeI'll disable this linter by default until these problems are solved#2022-03-0808:52borkdude#2022-03-0912:23timodo you know if I can specify a clj-kondo in clojure-lsp? I am on windows and seeing some problems...just wanted to try the latest.#2022-03-0912:25borkdudeyou can download the latest build from their CI, but they aren't using the problematic version#2022-03-0912:32timoah ok, good to know#2022-03-0912:32timothanks#2022-03-1013:39robert-stuttafordi would love a tool that allowed me to move vars between namespaces, and have it automatically update all the relevant namespaces correctly - adding new requires, removing old (but only if they're not already correct). is there such a thing? how close are we to being able to do this? what's the next step?#2022-03-1013:39robert-stuttaford(so, i'm talking about modifying the source code in an editor here, not the loaded vars in memory), like a refactoring tool#2022-03-1013:58borkdudeThe closest to this would be clojure-lsp. Try #lsp #2022-03-1014:02robert-stuttafordthanks!#2022-03-1014:36jumari think clj-refactor also has some facilities for that.#2022-03-1014:38jumar@U0509NKGK https://github.com/clojure-emacs/clj-refactor.el/wiki/cljr-move-form#2022-03-1016:17robert-stuttafordthat would be great if it did :as!#2022-03-1118:56JakubAccording to docs ^:replace is supposed to also apply to inner parts when merging configs, but it does not seem to work for me. Should both examples result in {:linters {:b 2}} or something else?
(clj-kondo.impl.config/merge-config! {:linters {:a 1}} ^:replace {:linters {:b 2}})
;; => {:linters {:b 2}}

(clj-kondo.impl.config/merge-config! {:linters {:a 1}} {:linters ^:replace {:b 2}})
;; => {:linters {:a 1, :b 2}}
#2022-03-1118:58borkdudeThere might be a bug, PR welcome to fix it#2022-03-1119:04borkdude@kloud Looking at the code, it seems ^:replace was ever only support to replace top level configs#2022-03-1119:06JakubThere are hints in the https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md that it should work for nested options: > The ^:replace metadata hint can be used to replace parts or all of the configuration instead of merging with previous ones. The home dir config is implicitly part of :config-paths. To opt out of merging with home dir config use :config-paths ^:replace [] in your project config.#2022-03-1119:07borkdudeTrue. And it does work for this particular case#2022-03-1119:08JakubI see, I inferred that it might work for other options 🙂#2022-03-1119:09borkdudeI guess it should not hurt performance too much if we check for meta on the deep-merge function, but it might be good to double check this on large merges#2022-03-1119:10JakubWould it make sense to have separate functions? add a new one for config merging and keep the old one for the analyzer for perf reasons?#2022-03-1119:12borkdudeI'm not sure if that distinction makes sense#2022-03-1119:15borkdudesince this merge with replace can happen anywhere#2022-03-1119:15borkdude(if we decide to support that)#2022-03-1119:15borkdudeI think checking meta should be fast and then getting the replace key if there is meta should also be fast, so the overhead should not be gigantic#2022-03-1119:15borkdudebut it's worth checking that#2022-03-1119:18JakubAnother option could be also a shallow merge of top-level keys. In my case I just need to override :linters but keep the inferred paths to keep hooks working.#2022-03-1119:20borkdudeI'm open to both options#2022-03-1119:37JakubI will give it a try#2022-03-1120:24Jakubhttps://github.com/clj-kondo/clj-kondo/pull/1611#2022-03-1120:25borkdudeI didn't realize you were that Jakub btw, good to "see" you again :)#2022-03-1120:26Jakubno conferences.. long time no see indeed 🙂#2022-03-1120:26Jakubare you coming to clojured in June?#2022-03-1120:28borkdudeyes#2022-03-1120:31Jakubcool, see you there#2022-03-1120:34borkdudeWe were discussing liz in #babashka-sci-dev recently, maybe it's fun for you to read it back#2022-03-1120:34borkdudeSee you there!#2022-03-1120:34borkdudeStill in Prague btw?#2022-03-1120:38Jakubyup, still in Prague :flag-cz:#2022-03-1119:04borkdudeMaybe that was intentional, not sure#2022-03-1313:07mindbenderWhat is the correct syntax for specifying configuration in the (ns ...)form?#2022-03-1313:14mindbenderI'm trying to turn of clojure-lsp warning messages about unused public vars in Calva IDE#2022-03-1314:04borkdudeSee config.md. I can post the link when I'm back at a keyboard #2022-03-1322:27borkdudeSo the config would be something like:
(ns foo
  {:clj-kondo/config '{:linters {clojure-lsp/unused-public-var {:level :warning}}})
#2022-03-1515:13Joshua Suskaloshould that be a commented form with #_?#2022-03-1515:14borkdudeno, not in the ns form#2022-03-1515:14Joshua Suskalookay, good to know. Is it basically an attrib map for the ns? I don't think I'd seen a map in the ns form before.#2022-03-1515:14borkdudeyes, this is a metadata map for a namespace#2022-03-1515:15Joshua Suskalothanks#2022-03-1319:52lreadI’m wondering about determining if a macro is part of a cljs api from clj-kondo analysis 🧵#2022-03-1319:54lreadI’m looking into this as part of https://github.com/cljdoc/cljdoc/issues/543 but it would also apply to tools like https://github.com/borkdude/api-diff#2022-03-1319:57lreadMy current understanding is that if :require-macros is used from cljs/cljc namespace x on clj/cljc namespace x then namespace x will have those macros available for use from a cljs client. (And there’s also :refer-macros and :include-macros sugar syntax but let’s leave that out maybe for the moment).#2022-03-1319:59lreadBut… I might be missing some common way folks include macros for consumption from a cljs api…#2022-03-1320:01lreadAfter I get a grip on how folks do include macros in their cljs apis. I’ll then want to figure out how to glean the cljs API from clj-kondo analysis data.#2022-03-1320:02lread@UKFSJSM38 did you have to make any similar determinations for your lsp work?#2022-03-1320:04ericdalloNot at all, clojure-lsp doesn't need to know that, we always rely on what kondo qualifies as macro or not#2022-03-1320:08lreadAh ok, thanks for letting me know @UKFSJSM38!#2022-03-1320:08lread@U04V15CAJ, do you have any thoughts/wisdom?#2022-03-1320:25borkdudemacros are always available from cljs#2022-03-1320:29borkdudeperhaps you can give me an example where this would not be the case#2022-03-1320:30lreadI guess I’m just trying to learn how cljs/cljc library authors typically expose macros for cljs consumption in their APIs.#2022-03-1320:31borkdudeyou cannot statically know if a macro is for public consumption or not, unless it's marked with skip-wiki or whatever#2022-03-1320:33borkdudeE.g. I'm pretty sure some of these macros are not for public consumption: https://cljdoc.org/d/org.clojure/core.match/1.0.0/api/cljs.core.match Yet they appear in the cljdoc output.#2022-03-1320:35lreadHmm… interesting.#2022-03-1320:38lreadI expect that cljdoc load-time analysis learnt of those because of https://github.com/clojure/core.match/blob/eec02931ead4dd86abe7bedea2d8e15ced6bc3de/src/main/clojure/cljs/core/match.cljs#L1-L2#2022-03-1320:40borkdudeI don't see why it needs that. Even without that the macros are publically accessible for any other cljs lib.#2022-03-1320:40lreadYeah technically true…#2022-03-1320:41borkdudeThese macros are even accessible by JVM clojure itself, so you cannot statically infer what is the intention behind those macros#2022-03-1320:41borkdudeAny guesses will be wrong#2022-03-1320:41lreadThanks that helps.#2022-03-1320:42lreadSo all clj macros are part of my cljs API unless :no-doc ed (or marked private).#2022-03-1320:43borkdudeyes#2022-03-1320:45lreadAnd if I do certain things as a library author, they might be easier to include from a cljs client, but that is besides the point.#2022-03-1320:47lreadWell, thanks, so nice to have smart people to ask these types of questions to!#2022-03-1320:49lread(I am thinking cljdoc cljs load-time analysis might need to be verified now, but am very happy that static analysis stays oh-so simple!)#2022-03-1518:02Sam Ritchieths is weird… I am having an issue in clj-kondo v2022.03.04 where if I delete my .cache , and then run clj-kondo --lint test/sicmutils/tex_web_test.clj , where sicmutils.tex-web-test IMPORTS sicmutils.env, that in my hook, (api/ns-analysis 'sicmutils.env) returns {}. which makes it impossible for my hook to look at this info and expand to a bunch of declare forms.#2022-03-1518:03Sam Ritchiebut then if I explicitly invoke clj-kondofor src, where sicmutils.env lives (basically point it AT the file), then the next time the cache is full#2022-03-1518:04Sam Ritchieso to be clear, if I call this twice:
clj-kondo --lint src:test
it first fails, then succeeds
#2022-03-1518:17borkdudeyes, that's expected, ns-analysis depends on the cache.#2022-03-1518:23Sam Ritchiebut I would have thought the cache would be populated for B by B’s requirements?#2022-03-1518:23Sam Ritchieor is the cache only filled at the end of a run#2022-03-1518:27borkdudeyeah#2022-03-1518:27borkdudethere is no pre-analysis of namespace dependencies#2022-03-1518:28borkdudeclj-kondo just lints files in random order and figures stuff out and the end#2022-03-1518:28borkdudeI'm considering adding a pre-analysis of ns dependencies, but it's currently not there#2022-03-1518:29borkdudeit would also complicate parallel linting#2022-03-1522:45Sam Ritchienoticed that #(gensym %) triggers redundant fn wrapper in cljs; but gensym is a macro here, so I would suggest that this be an exception to that rule#2022-03-1522:48dpsuttonwhere is gensym a macro? (repeatedly 5 gensym) and (source gensym) indicate that it is not#2022-03-1522:48borkdude
$ plk
ClojureScript 1.10.914
cljs.user=> gensym
#object[Function]
#2022-03-1523:03Sam RitchieOh I misunderstood from this and a strange test error I was getting #2022-03-1523:03Sam Ritchie@#2022-03-1523:04Sam RitchieSorry, long day at the REPL! I'll debug that weird error#2022-03-1523:14Sam Ritchieit was this for the record:
actual: #object[TypeError TypeError: cljs.core.gensym.cljs$core$IFn$_invoke$arity$1 is not a function]
#2022-03-1523:15Sam Ritchiewon’t reproduce at the REPL#2022-03-1523:19borkdudeIssue + repro welcome#2022-03-1602:12Sam RitchieFixed once I got some rest. I was rebinding gensym but not covering the 0 arity case, since I didn’t think anyone else was calling it inside my with-redefs#2022-03-1602:12Sam Ritchiefalse alarm!#2022-03-1707:11robert-stuttafordis it possible to squash a deprecation warning for a specific var, at the config.edn level? i know that i can #_:clj-kondo/ignore them one by one, but it'd be great if i could do it once for the whole codebase warning: #'hiccup.core/html is deprecated since 2.0#2022-03-1707:32borkdudeYes, see linters.md#2022-03-1707:33robert-stuttafordlol, why did i fail to find that myself. thanks and sorry!#2022-03-1707:37robert-stuttafordgot it sorted, thanks sir#2022-03-1707:41borkdudeNo problem :-) I'm afk, so short reply#2022-03-1707:43robert-stuttafordconcise and correct, like all good clojure code#2022-03-1714:48dpsuttonI was about to make an issue about this but want to check that I’m not doing something dumb:
(ns bug
  (:import java.util.Collection))

(defmulti foo {:arglists '([^Collection coll])} first)
clj-kondo is reporting the import of j.u.Collection is unused. Not clear to me if • it is unused because that typehint isn’t doing anything • it is used by clj-kondo is getting thrown because it is inside of a quoted form
#2022-03-1714:49dpsuttoninterestingly, changing it to
(defmulti foo {:arglists (list [^Collection 'coll])} first)
did not remove the unused warning
#2022-03-1714:49borkdudeit's a bug.#2022-03-1714:49borkdudebut why do you place type hints on the arglists?#2022-03-1714:50borkdudeI mean, that is valid, just wondering why#2022-03-1714:52borkdudeissue welcome#2022-03-1714:52dpsuttonno idea. it is before my time#2022-03-1714:53dpsuttontyped up the issue and github 500'd 😞#2022-03-1714:54dpsuttonhttps://github.com/metabase/metabase/blob/master/test/metabase/test/data/sql.clj#L10 is the import and https://github.com/metabase/metabase/blob/master/test/metabase/test/data/sql.clj#L247 is the usage#2022-03-1714:55dpsuttonBut i wanted to ask here because i was aware “that is a really dumb thing to do” might have been an answer 🙂#2022-03-1714:55borkdudeneh, this should not result in a lint warning#2022-03-1714:55dpsuttonyeah it felt both like “that’s dumb, but it should work, but its still dumb”#2022-03-1717:04borkdudeI had a closer look and commented on the issue, it probably wasn't a bug after all#2022-03-1808:14ikitommiit seems that I would like to push the clj-kondo config.edn into git, but nothing else, could the config be in the top-level folder? currently doing this in .gitignore:
.clj-kondo/*
!.clj-kondo/config.edn
#2022-03-1808:29borkdude@ikitommi both lsp and clj-kondo have the convention that you can just put
.cache
in your .gitignore so it will work for both projects
#2022-03-1808:41ikitommi… but, under clj-kondo, there are the folders per package too? e.g. babashka, com.gfredericks, …#2022-03-1808:42ikitommi…. or are these just ghosts from older versions of clj-kondo?#2022-03-1808:43borkdudethese are configurations imported automatically while scanning the classpath#2022-03-1808:43borkdudeyou can disable this in .lsp/config.edn :copy-kondo-configs? true#2022-03-1808:43borkdudeyou are probably seeing these configs because of babashka support in lsp#2022-03-1808:44borkdudeif you are using those configs, you can check them into source control, else you can ignore / delete them#2022-03-1809:12ikitommiI think it’s good to have them, just not in the version control as they get created automatically and don’t need versioning.#2022-03-1809:13ikitommiif the config.edn is the only relevant file, this should be ok:
.clj-kondo/*
!.clj-kondo/config.edn
#2022-03-1809:14ikitommi… but maybe if the configurations were imported under one folder, it would be easy to exclude, maybe even under .cache?#2022-03-1809:25borkdude> I think it’s good to have them, just not in the version control as they get created automatically and don’t need versioning. This isn't true. They are only copied from the dependencies because lsp does this. If you want to have the same linting in CI, it's good to version those things into version control.#2022-03-1809:26borkdudeThe recommended way is to include them into version control, so everyone who uses clj-kondo with this repo gets exactly the same linting, whether you use lsp or not#2022-03-1815:41ikitommigood to know, thanks!#2022-03-1809:02lassemaattais it normal for clj-kondo to warn about the new clojure.core/parse-? functions even when using org.clojure/clojure 1.10.3?#2022-03-1809:02lassemaatta
[
#2022-03-1809:02lassemaattaclj-kondo v2022.03.09#2022-03-1809:03lassemaattaI'm creating the local cache with the typical --dependencies --parallel --copy-configs#2022-03-1809:04lassemaattathe clojure.core.transit.json within the cache does not (obviously) mention the new parse- functions#2022-03-1809:30borkdudeif you lint dependencies using clj-kondo --lint $(clojure -Spath) this should reset to the clojure version you are using locally#2022-03-1809:32borkdudeyou can add :refer-clojure :exclude [parse-long] in your namespace to prevent the warning, makes it future-proof anyway#2022-03-1809:47lassemaattahmm.. if I do something like clj-kondo --lint $(clojure -Spath) --lint some-path-in-project I still get warnings about parse-long, parse-double. Even if I clear the cache. Of course, it's a good idea to deal with those functions, as you said, but I'm curious why do we get these warnings.#2022-03-1809:47lassemaattaand to be clear, clojure -Spath returns src:/home/lassemaatta/.m2/repository/org/clojure/clojure/1.10.3/clojure-.10.3.jar:/home/lassemaatta/.m2/repository/org/clojure/core.specs.alpha/0.2.56/core.specs.alpha-.2.56.jar:/home/lassemaatta/.m2/repository/org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.jar#2022-03-1809:48borkdudedo you have a .clj-kondo directory? this is a requirement for the cache to be saved#2022-03-1809:48lassemaattasure#2022-03-1809:49borkdudecan you try:
mkdir -p .clj-kondo
clj-kondo --lint $(clojure -Spath) --dependencies
#2022-03-1809:49borkdudeexactly that#2022-03-1809:50lassemaattadone#2022-03-1809:50borkdudeand still the warning about parse-long?#2022-03-1809:50lassemaattayes#2022-03-1809:51borkdudeon the command line?#2022-03-1809:51lassemaattayes 🙂#2022-03-1809:51borkduderepro welcome#2022-03-1809:51lassemaattaand as I mentioned previously, I looked into the cache and at the clojure.core.transit.json file and found no references to the parse- -functions within#2022-03-1809:52borkdudeok, so the transit file is updated to the newest#2022-03-1809:52borkdudeto your own version of clojure#2022-03-1809:52lassemaattano problem, I'll see if I can build a repro 🙂#2022-03-1809:53lassemaattaoh and thanks for you help debugging this, much appreciated 👍#2022-03-1812:44lassemaattahttps://github.com/clj-kondo/clj-kondo/issues/1619 with a link to a simple repro project#2022-03-1812:53borkdudeAh I see yeah. This is probably a won't fix as there is a list of clojure vars built-in independent of version and it's already bumped to 1.11. Just future-proof your repo using :exclude#2022-03-1812:53borkdudeThanks for repro-ing.#2022-03-1812:54lassemaattaah, ok 👍#2022-03-1811:11robert-stuttafordgot a bit of a headscratcher, where although i am specifying an exclude for unused-namespace, it's not being applied. pictured: the file that's being linted, and the output from kondo, with just that linter's config displayed. you can clearly see the namespace, the file path, the error, and the exclude pattern. both the dep and the cli are on 2022.03.09. what should i do next to diagnose?#2022-03-1811:12robert-stuttafordi've already read all the relevant kondo source and i don't have a hypo for why this may be; it all looks correct!#2022-03-1811:14robert-stuttafordhttps://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/config.clj#L197-L208 https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/linters.clj#L443#2022-03-1811:20borkdudePossibly you have :skip-comments true?#2022-03-1811:22robert-stuttafordi definitely have!#2022-03-1811:22borkdudeThat acts as if the comment doesn't exist. There is now something far better:
{:config-in-comment {...}}
#2022-03-1811:23borkdudeJust use that instead and disable any linters you don't want to activate in comments#2022-03-1811:23borkdude:redefined-var is already deactivated automatically#2022-03-1811:23robert-stuttaford{:config-in-comment {:linters {:unresolved-namespace {:level :off}}}}#2022-03-1811:23robert-stuttafordyes this is so much better!
#2022-03-1811:23borkdudefor example yes#2022-03-1811:25robert-stuttafordhm. with that in, i'm still getting the warnings. surely the presence of a comment form is irrelevant here? i wish to control the linting of the top-level ns form#2022-03-1811:26borkdudeoh right sorry :)#2022-03-1811:26borkdudewhat's your config?#2022-03-1811:26robert-stuttafordhehe :)\#2022-03-1811:27robert-stuttaford
{:linters {:unused-namespace {:exclude ["^dev.*$"]}}
 :skip-comments true}
#2022-03-1811:27robert-stuttafordother than this, we have a bunch of lint-as and a bunch of hooks#2022-03-1811:27borkdudewell, clojure.data.csv doesn't match this regex?#2022-03-1811:27robert-stuttafordohhh man#2022-03-1811:28robert-stuttafordso the exclude is about the requires themselves, not the ns in which the unused require is?#2022-03-1811:28borkdudeexactly :)#2022-03-1811:28robert-stuttafordhi i'm robert and i am a professional haha#2022-03-1811:28borkdudehehe, no problem#2022-03-1811:29robert-stuttafordok so there's no way to do what i thought it did, right#2022-03-1811:29robert-stuttafordi'd basically have to add a rule to each ns in dev/* separately#2022-03-1811:30borkdudeaha so in dev* you want to disable a linter, I see#2022-03-1811:30robert-stuttafordyessir#2022-03-1811:30robert-stuttafordcos its full of scripts we use via remote repl, with all the meat in comment forms#2022-03-1811:31robert-stuttafordso we specifically don't care about unused requires in just this source folder#2022-03-1811:31borkdudeif you move those requires to comment forms then it would be possible...#2022-03-1811:31borkdudeit would not be very hard to support this though#2022-03-1811:31borkdude
(comment
  (require '[clojure.data.csv])
)
is the current workaround
#2022-03-1811:32robert-stuttafordok, thanks man, i appreciate your time on this, very helpful#2022-03-1811:33borkdudeissue is welcome.#2022-03-1811:34robert-stuttafordi'll add one for the idea of being able to prevent a rule running within (rather than about) a pattern of namespaces#2022-03-1811:34robert-stuttafordit's really just the generalisation of :namespaces here#2022-03-1811:35borkdudeyeah, thanks. clj-kondo already generalized :config-in-comment as :config-in-call {clojure.core/comment ...}#2022-03-1811:35borkdudebut we need :config-in-namespace too#2022-03-1811:39robert-stuttafordhappy with the language? https://github.com/clj-kondo/clj-kondo/issues/1618#2022-03-1811:41borkdudeYep!#2022-03-1811:41borkdudeNote that for CI purposes you could lint your sources in multiple steps with different configs#2022-03-1811:43robert-stuttafordyeah. what we're trying to do right now is get one config in use in hooks and in CI, and with zero known issues. then we'll try to work to keep issues to zero. so, it's important that our editors, our pre-commits, and our CI all agree on what an error / warning is#2022-03-1811:44robert-stuttafordthe other thing is we want our entire classpath to remain compilable so that e.g. lsp or clj-refactor doesn't break when using find-usages or similar#2022-03-1811:45robert-stuttafordthanks @U04V15CAJ! have a great weekend man!#2022-03-1811:18robert-stuttafordonce the issue above is resolved, our 161kloc Clojure codebase will be at zero warnings, zero errors 😄#2022-03-1821:07aptHi folks. Consider the function below:
(defn path
  [url]
  (keyword (re-find (re-matcher #"(?<=\{\{services\.).*?(?=\}\})" url))))
example of usage:
(re-find (re-matcher #"(?<=\{\{services\.).*?(?=\}\})" "{{services.blueprint}}/api/v2/services"))
;; blueprint
Because of keyword, I’m getting this error:
clj-kondo: Expected: symbol or string or keyword, received: seq.
Is this expected?
#2022-03-1821:10borkdudeThat seems like a bug. I will create an issue. Workaround:
(defn path
  [url]
  (keyword #_:clj-kondo/ignore (re-find (re-matcher #"(?<=\{\{services\.).*?(?=\}\})" url))))
#2022-03-1821:12borkdudeI guess clj-kondo assumed the return value would be something like:
user=> (re-find (re-matcher #"foo" "foo"))
"foo"
user=> (re-find (re-matcher #"(foo)" "foo"))
["foo" "foo"]
#2022-03-1821:13aptThanks! Yeap, makes sense.#2022-03-1821:18Drew VerleeIs there clj-kondo linter config/code that can help mark places where form 2 components aren't properly passing there arguments on. eg
(defn outer 
  [a b c]            ;; <--- parameters
  ;;  ....
  (fn [a b c]        ;; <--- forgetting to repeat them, is a rookie mistake
    [:div
      (str a b c)]))
#2022-03-1821:18borkdudeThis is a reagent component right?#2022-03-1821:18Drew Verleecorrect#2022-03-1821:19borkdudeIf reagent had some marker functions then we would be able to write a hook for it#2022-03-1821:19borkdudebut right now you cannot see statically that a function is a reagent component#2022-03-1821:19Drew Verleeyea. thats what i was worried about. errr.#2022-03-1821:26borkdudeif you write a custom macro that just passes the body to defn, e.g.
(defmacro component [& body]
  `(defn 
Then you could write a hook for that.
(component [x y]
  (fn [x y] ...))
#2022-03-1821:26borkdudeBut I guess reagent also has with-let for this right?#2022-03-2015:09borkdudeclj-kondo is today 3 years old! https://twitter.com/borkdude/status/1505558955287789571 thanks to everyone joining me on this journey!#2022-03-2015:14Sam Ritchiewoohoo!#2022-03-2116:54snoeI'm out of practice with the internals of analysis, but is it possible to know that a macro like myfor is treated as clojure.core/for I think not? Here's my problem: I was hoping to handle extracting vars (`move-to-let` in clojure-lsp) into (for [:let []]) bindings when appropriate, right now we just match raw symbols but analysis could improve that (similar issues exist identifying let like macros). The other thing I'm thinking of is how a cond-let macro would/should behave with extract var refactors, but it'd be nice to enable it. Maybe something could be annotated with like-let or like-for or like-params and that way hooks could take part (but I don't think the various vectors appear in analysis)?#2022-03-2116:56snoeMaybe the way hook expansion works, I would see a clojure.core/let ? Before I go digging in again, just wondering if there's anything existing to be aware of?#2022-03-2116:58borkdudeCustom macros like cond-let are best handled using hooks and then you would indeed see the locals as a normal let, usually#2022-03-2116:59borkdudeMaybe you can demontrate your question/problem using a repro showing that something is or is not possible using the current state of affairs, I'm not really sure from the top of my head#2022-03-2116:59borkdude@UKFSJSM38 has been dealing a lot with analysis as well#2022-03-2121:09snoeHere's an example @U04V15CAJ given this file and config:
(ns scratch.core)

(defmacro forv [& args]
  `(vec (for 
:lint-as {scratch.core/forv clojure.core/for} If I put the cursor on the (inc n) and perform move-to-let / extract var refactor, I would want to transform it to (forv [n [1 2 3] :let [m (inc n)]] m) but without knowing that I should treat forv as for I can only do (forv [n [1 2 3]] (let [m (inc n)] m))
#2022-03-2121:15snoeDumping the analysis for it, I can't see how to draw that connection that lint-as provides with what's there.#2022-03-2121:17ericdalloHum, got it, we would need something just like we know a var-definiton was defined-by clojure.core/deftest for example, but for a var-usage#2022-03-2121:23snoeIt may even be trickier, because we probably need to know the binding vector itself can be treated like for 's (or let or params etc.. Imagine this one with a weird first arg.
(defmacro forv [message & args]
  `(do (println ~message) (vec (for 
#2022-03-2121:43borkdudeisn't move-to-let a bit ambiguous here? it could also mean: move to an outer let:
(let [x 1] (forv ...))
#2022-03-2121:45borkdudethat one with the first weird arg would not be possible with lint-as, so you would need to write a hook for that one#2022-03-2121:46borkdudeI think it's reasonable to expect these refactorings to work for core macros and less so for custom macros#2022-03-2121:47borkdudeIt's probably best to wait for people to really complain about this, I could imagine that it isn't worth the trouble of solving this at all#2022-03-2121:56snoeYeah, I'm not too sympathetic to weird macros. But every large code base ive run into builds their own lint-as like macros. I guess if we focus on lint-as maybe we could just use the kondo config itself and not need analysis. wdyt @UKFSJSM38?#2022-03-2122:00borkdudethat's maybe a good idea initially#2022-03-2207:47Sam Ritchiehey all, I’m hitting a problem where in a project that takes sicmutils as a dependency, any namespace that tries to use a form like new-sym defined in sicmutils.env with (import-def original-value new-sym) fails to recognize sicmutils.env/new-sym, EVEN THOUGH namespaces inside the project work fine. repro here: https://github.com/sritchie/kondo-repro#2022-03-2207:48Sam Ritchiethe rule I wrote for this definitely triggers when I lint dependencies, which I would have assumed would populate the cache. The import-vars rule for potemkin on the other hand does not seem to have any trouble in this case, so I am guessing it is a problem with my hook? but weird that it only shows up in dependencies…#2022-03-2208:38borkdudeCan you create a github issue?#2022-03-2208:41borkdudeI'm busy today so no time to look at it, perhaps later this week.#2022-03-2208:42borkdudeI did notice this:
cat .clj-kondo/.cache/v1/cljc/sicmutils.env.transit.json | jet --from transit --query ':clj keys' --pretty
The principal-value var doesn't appear in there.
#2022-03-2208:42borkdudePlease append that info to the issue as well.#2022-03-2208:50Sam Ritchiesounds good!#2022-03-2208:54Sam Ritchiehttps://github.com/clj-kondo/clj-kondo/issues/1626#2022-03-2210:53fadrianHow do I get rid of unused-public-var warnings in Calva? From what I gather, these come about via Calva's use of clojure-lsp, which uses a custom linter in clj-kondo to generate these. I've tried adding #clj-kondo/ignore and #{:clj-kondo/ignore [:unused-public-var]] before the statement throwing the warning, but neither of these seem to work. Any ideas?#2022-03-2211:12ericdallohttps://clojure-lsp.io/settings/#diagnostics-linter#2022-03-2211:12ericdalloThe correct linter name is :clojure-lsp/unused-public-var#2022-03-2211:13ericdalloAlso, it's a info,.not a warning#2022-03-2313:57fadrianSorry, forgot to send this yesterday: Thank you.#2022-03-2213:51rafaeldelboniHi hello, what is the best approach to create a custom kondo rule, to warn me about println and prn that I forgot in my code after a debug session?#2022-03-2213:52borkdude@rafaeldelboni you can write a hook for it. docs: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2022-03-2213:55rafaeldelboniOh thanks this is exactly what I was looking for https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#disrecommend-usage-of-function-or-macro#2022-03-2213:53borkdudeA linter that would be able to catch that is https://github.com/clj-kondo/clj-kondo/issues/996 but it hasn't been implemented yet. https://github.com/clj-kondo/clj-kondo/issues/996#2022-03-2213:54borkdudeFeel free to comment/upvote it#2022-03-2213:55rafaeldelboniThat would be a nice feature#2022-03-2213:56borkdudeI mean in the issue#2022-03-2213:56rafaeldelbonisure 😅#2022-03-2213:56borkdude:-D#2022-03-2213:56borkdude<3#2022-03-2311:16Charlie BriggsI was wondering if I'm doing something funny to get this issue when using the claypoole config from clj-kondo/config: https://github.com/clj-kondo/config/issues/13 It's causing issues with using claypoole, which we use frequently - any references within the cp bodies are reported as unused#2022-03-2321:50AJ JaroWe have a mono-repo with a few projects within it. When I have the File Watcher IntelliJ plugin configured to run clj-kondo on a sub-project it won’t pick up the parent config if there is a .clj-kondo directory that exists in the sub-project. Here’s an example structure. If I edit a file within the projects folder I would expect that the parent config.edn is picked up, but it doesn’t seem to work that way
.
| 
 -- .clj-kondo
   |
    -- config.edn
|
 -- projects
   |
    -- .clj-kondo
      |
       -- metosin
...
#2022-03-2321:51borkdudeIt does not work that way. clj-kondo does not merge configs from parent directories, but you can refer to a shared configuration using :config-paths.#2022-03-2321:52AJ Jarook, thanks. A config.edn doesn’t exist in the projects folder, so there (theoretically) should be nothing to merge#2022-03-2321:53borkdudeThe closest .clj-kondo directory to the file you are editing is the one that gets picked up.#2022-03-2321:53borkdudeIf you want to include config from some other place, you should use :config-paths#2022-03-2321:54AJ Jarogotcha, fair enough#2022-03-2321:54AJ JaroThat directory gets automatically created by “some process” (🤷 ) and I suppose I can just add a config file pointing to the proper place#2022-03-2321:55borkdudeclj-kondo doesn't automatically create a .clj-kondo directory, but some kind of editor tooling might be doing that#2022-03-2321:57borkdudeusually when you have a deps.edn or project.clj and you open that directory as a project in an editor, then clojure-lsp or so might be creating a .clj-kondo to store analysis information there#2022-03-2321:57borkdudeor #clj-extras-plugin#2022-03-2321:57borkdudeas it assumes that that is the root of the project#2022-03-2321:59borkdudein general, there should be only one .clj-kondo directory per project. if you have a mono-repo then there should be one .clj-kondo directory for each project in that repo#2022-03-2322:00borkdudeand you can have a shared configuration for all of these projects, adding that happens through :config-paths#2022-03-2322:22AJ JaroGotcha, that helps. Thank you. It could be clojure extras, who knows. but the config paths is the right way forward for us I think#2022-03-2323:47jacob.maineAt startup clojure-lsp calculates the classpath and if anything has changed, asks clj-kondo to analyze the entire classpath. Most files on the classpath will be unchanged, meaning a lot of extra work is done. We were just brainstorming ways to make that faster. One of the ideas would be for clj-kondo to keep a cache of its analysis. Has that idea ever been discussed?#2022-03-2323:48jacob.maineObviously it’s something we could do in clojure-lsp itself, but I thought I’d bring it up here in case it’d be useful for the larger clj-kondo community#2022-03-2400:31ericdalloExample: if one of the paths, like /path/to/.m2/repository/org/codehaus/plexus/plexus-utils/3.4.1/plexus-utils-3.4.1.jar passed to kondo was already linted before by clj-kondo, there is no need IMO to re-lint, clj-kondo could cache the output analysis of that, right?#2022-03-2406:56borkdudeYou should cache analysis yourself as the things you want to cache are different per application. Clj-kondo has its own cache specifically optimized for its own linting #2022-03-2406:57borkdudeClj-kondo also skips the jar if it has linted it before already but not when config changes since it might affect any analysis of any lib #2022-03-2323:59dpsuttonhere’s a weird one. Lovely to mark vars as unused with a prefix. _db. Should it lint if those vars are prefixed but are used?#2022-03-2406:54borkdudeThere's already a linter for that#2022-03-2417:49Maris
(api/POST "/update-settings" []
         :summary "Updates settings"
         :body [body-params {(s/optional-key :url)                       s/Str
                             (s/optional-key :external-data-provider-id) s/Str
                             (s/optional-key :external-branch-id)        s/Str}]
#2022-03-2417:50MarisHow can I get rid of unresolved body-params error in this code ^^^#2022-03-2417:58Mariscompojure.api.sweet/POST clj-kondo.lint-as/def-catch-all#2022-03-2419:45borkdude@maris.orbidans I think you are looking for :linters {unresolved-symbol {:exclude [(compojure.api.sweet/POST)]}}#2022-03-2419:45borkdudeSee https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#unrecognized-macros#2022-03-2513:57Marishello#2022-03-2513:58Mariskondo complains about clojure 1.11 functions in emacs#2022-03-2513:58MarisI added clojure dependency to :dev profile#2022-03-2513:59MarisIt worked only for command line#2022-03-2514:00MarisIs it possible to get rid of parse-double warnings in emacs ?#2022-03-2514:00MarisI am using flycheck-clj-kondo#2022-03-2514:02borkdudeCan you be more specific, using a repro, e.g. example.clj?#2022-03-2514:13Maris
(defn- ->rounded-int [s]
  (some-> s parse-double Math/round))
#2022-03-2514:14Maris
parse-double
^ unresolved symbol
#2022-03-2514:14borkdudeWhich version of clj-kondo are you using and is this in .cljs or .clj?#2022-03-2514:14borkdudeor .cljc?#2022-03-2514:15Marisclj , [clj-kondo "2022.03.09"]#2022-03-2514:16MarisIt works from command line, after I added [org.clojure/clojure "1.11.0"]#2022-03-2514:17Maristo my dev profile in project.clj#2022-03-2514:21borkdudeare you sure that flycheck-clj-kondo is using the same version as you're using on the command line?#2022-03-2514:21borkdudecan you do $ clj-kondo --version ?#2022-03-2514:23Marisah that explains it, clj-kondo v2021.04.23#2022-03-2514:24MarisI thought it would use version from project.clj :man-facepalming:#2022-03-2514:25borkdude:-D glad it's solved. no it uses the binary#2022-03-2709:28borkdudehttps://twitter.com/borkdude/status/1508013046047850496 😎#2022-03-2718:38snoenice, do you look for .java files in jars before decompiling?#2022-03-2718:43borkdude@U0BUV7XSA That's on clojure-lsp, clj-kondo just gives a list of all classes, including .java and .class, so clojure-lsp should prioritize on .java#2022-03-2718:44snoenice that we get both tho.#2022-03-2811:02pedrorgirardi#2022-03-2811:02pedrorgirardi#2022-03-2811:03pedrorgirardi@borkdude @ericdallo I’m testing the Java class definitions & usages and I found this behavior a bit strange: java.util.Date doesn’t appear in java-class-usages, it does appear in var-usages though.#2022-03-2811:04borkdude@U5GP9FMC0 via import it should work, the other one will be tackled on Wednesday or so. https://github.com/clj-kondo/clj-kondo/issues/1633 Please mention in the issue that there is an incorrect var-usage there as well#2022-03-2811:05pedrorgirardiCool! I will leave a comment. Thanks 🙂#2022-03-2812:17Noah BogartThis might be a dumb question, but given that Clojure is open source, why is it necessary to decompile the clojure.core stuff instead of pointing at the source itself? Do the clojure jars not include the source inline? (My apologies if this would be better suited for another channel)#2022-03-2819:14snoei was wondering that too. my clojure.core 1.11 jar in m2 only had .class files. Might be something to bring up with core team#2022-03-2812:19borkdude@nbtheduke It's not necessary if the .java sources are on the classpath, but this is not always the case, so decompilation is used only as a fallback#2022-03-2908:02jamescroftHi 👋 . Just wondering if there is a reason that :namespace-definitions doesn’t include the :end-row and :end-col keys, or whether they are something that could be added?#2022-03-2908:11borkdude@U06790Y4E does you mean, the end of the ns form?#2022-03-2908:12borkdudeor what should end-row and end-col be?#2022-03-2908:18jamescroftYes, given :row and :col correspond to the start of the ns form (I think), it would be good to have end-row and end-col correspond to the end of the ns form. Like how var-definitions works.#2022-03-2908:20borkdudeI think that makes sense. Issue + optional PR welcome#2022-03-2908:21borkdudeMay I ask how you are using this?#2022-03-2908:30jamescroftSure. I am using the analysis data to find things and extract the text from the source strings. I need the start and end for this.#2022-03-2908:32borkdudeYep, makes sense#2022-03-2914:04andrea.crotticouple of things I always struggled a bit with clj-kondo config (also because I haven't done it so much) • I never know how to exclude something properly, for example for unresolved-symbol it takes a list while for unused-referred-var requires a map. And also not all the linters can have an exclude right? • silly mistakes in the config just fail silently, for example I had :unused-import as top level key instead of under linters and you don't get any warnings. I think in theory is possible to do a schema check of the whole config right to see that the structure/types are correct? Anyone has thoughts about these two points?#2022-03-2914:23borkdude@andrea.crotti All linter docs are in https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md There could be some improvements to linting clj-kondo's own config. There's also ready something in place for that.#2022-03-2915:23andrea.crottiyeah I know I use the docs, so every possible configuration would be mentioned there then?#2022-03-2915:24andrea.crottiwherever exclude is not mentioned it just means is not supported for that linter right?#2022-03-2915:24borkdude> so every possible configuration would be mentioned there then? yes and yes#2022-03-2915:29andrea.crottiok cool#2022-03-3016:27papachanthis meta was working recently on my CI flow. but right now its not igoring file on my local env
#_:clj-kondo/ignore
#2022-03-3016:27borkdudemore info needed#2022-03-3016:31papachanI put this line on top of my files with some expected lint error. i believe my clj-kondo task lint from my CI flow respect this. But right now i just see my local env not. which is using a latest version of clj-kondo.#2022-03-3016:31borkdudeThis only applies to a form, not a whole file#2022-03-3016:32papachanAhhhh#2022-03-3016:33papachanthat was my confusion#2022-03-3016:34borkdudeyou can disable linters in a file using namespace metadata though#2022-03-3016:34borkdudeand there's also a regex option globally#2022-03-3016:34borkdudeSee https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#2022-03-3105:19Ben SlessIs it possible to use kondo for side effect linting / analysis? For example require a function should be pure then get a lint error if this assumption is violated, or query a function if it has side effects?#2022-03-3105:30lassemaattaI'm curious; how would/could you detect if a function has side-effects? By manually adding some explicit metadata or something like that to "color" the functions?#2022-03-3105:39Ben SlessInitially, yes. I think if you default to "all interop is impure unless explicitly stated" and propagate this upwards you'll be 95% there#2022-03-3105:40Ben SlessEven all printing ends up with .append and flush#2022-03-3105:50lassemaattaah, ok. I think this is one of those questions where that last 5% contains all sorts of nasty edge-cases. A silly function like (defn foo [*a] (swap! *a inc) sure looks quite side-effecting in isolation, but perhaps it's (sometimes) invoked from (defn bar [val] (let [*a (atom val)] (foo *a) @*a)) etc 🙂 or in case of printing your function might be wrapped in with-out-str#2022-03-3106:06Ben SlessThat's where you do "fun" things like life-time analysis#2022-03-3106:31Ben SlessIsn't it similar to the go block analyzer marking transitions?#2022-03-3110:46borkdude@UK0810AQ2 Could work to a certain degree, but what kind of input/output would you expect? Need more specific examples.#2022-03-3118:46Joshua SuskaloI think that "all interop is impure" would be pretty troublesome in a lot of codebases considering you'd have to, for one, manually examine most of clojure core for this since so much of it delegates to clojure.lang.RT, and then a lot of very common data structure libraries like sorted maps etc. would then have to get custom linting as well considering their authors are unlikely to package clj-kondo configs. Not saying it's impossible by any stretch to start from there, but it definitely feels like it would require a lot of community effort.#2022-04-0105:47Ben Sless@U04V15CAJ I think there are linters you can build on top of this analysis. Few ideas: Maximum recommended depth for side effects Maximum number of side effects in function call Assertions - specify a certain function must remain pure, then down the line trip that linter if something violated this assumption#2022-03-3113:35sheluchinShould there be a warning for something like this?
(defn foo
  ([x & {:keys [y]
         :or {y false}}]
   (foo x y))
  ([x y]
   [x y]))
Looks like clj-kondo has no problem with it, but Clojure gives:
Syntax error compiling fn* ...
Can't have fixed arity function with more params than variadic function
#2022-03-3113:37borkdudeyes, clj-kondo should lint this. there might be an issue but if not, feel free to create it#2022-03-3113:43sheluchinhttps://github.com/clj-kondo/clj-kondo/issues/1643 Thanks @U04V15CAJ.#2022-03-3113:46borkdudeThanks#2022-03-3115:03lreadI just muddled through how to configure clj-kondo to ignore an assert expr brought in by https://github.com/nubank/matcher-combinators. In the end it was an easy :unresolved-symbol {:exclude [(clojure.test/is [match?])]} in my clj-kondo config. Might be worth me adding a tip under https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-symbol docs?#2022-03-3115:05borkdudeisn't that already in there?#2022-03-3115:18lreadMaybe, but not as an explicit example for test assert expressions.#2022-03-3115:19borkdude
{:linters
  {:unresolved-symbol
    {:exclude [(riemann.streams/streams [where])]}}}
is a similar example?
#2022-03-3115:19borkdudeoh yes, I think adding the clojure.test example is much better and more common. PR welcome#2022-03-3115:19borkdudewe can replace the existing example#2022-03-3115:21lreadOk, will do.#2022-04-0316:40Carlois there a configuration to prevent clj-kondo to trigger the unresolved symbol warning on logical variables (ie. symbols that start with ? , used in some dsls like #meander)?#2022-04-0316:41borkdudeRight now no, but this is something I would consider, e.g. exclude by regex#2022-04-0316:44Carlois my best bet for now to turn off the whole unresolved symbol category?#2022-04-0413:54wilkerluciomaybe this can help you, this is how I'm handling Meander in Kondo nowadays:
:linters {:unresolved-symbol {:exclude [(meander.epsilon/match)
                                         (meander.epsilon/find)
                                         (meander.epsilon/search)
                                         (meander.epsilon/rewrite)]}}
#2022-04-0316:44borkdudePlease file an issue with a good explanation and examples. @dpsutton I saw a couple of these variables in Metabase's code-base too, right?#2022-04-0316:44borkdude@meditans Oh god, no, you can disable it for only some calls, like :exclude [(meander.epsilon/match)]#2022-04-0316:45dpsuttoni think that's unrelated. we have lots of $id type variables which are a dsl macro to pull from databases at test run time#2022-04-0316:45borkdudeyes, but the relation would be that those variables are sometimes also unresolved, if you don't have special hooks for those macros - maybe I'm wrong#2022-04-0316:46dpsuttonyes good point. they are unresolved and symbols that get meaning from the macro itself and not a previous definition#2022-04-0316:47borkduderight, so a regex exclusion would also work for that#2022-04-0317:05Carlothe relevant issue https://github.com/clj-kondo/clj-kondo/issues/1647#2022-04-0403:09fabraohow to I ignore Unused public var if defn have specific metadata?#2022-04-0403:10fabraolike this
(defn ^{:resolver :query/usuario_by_id} usuario-by-id [conexoes]
  (fn [_ _ _]
    "OK"))
#2022-04-0403:51Joshua Suskalothis lint comes from #lsp, you'd need to see if lsp allows you to configure it to be based on meta#2022-04-0403:10fabraoI use it dynamic, not directly#2022-04-0507:49mkvlrI just noticed that it’s possible to show lint warnings inline on github PRs, seen for elixir below. Looks like it’s done by these https://github.com/erlef/setup-beam/blob/main/.github/elixir-matchers.json. Does a similar thing exist for clj-kondo or should we build it?#2022-04-0507:50mkvlrhttps://github.com/actions/toolkit/blob/main/docs/problem-matchers.md#2022-04-0508:01borkdudeDo you mean like this one? https://github.com/marketplace/actions/clj-kondo-checks#2022-04-0508:30mkvlryep#2022-04-0508:30mkvlrdo you use it on your projects?#2022-04-0508:57borkdudeI'm using it on clj-kondo :)#2022-04-0507:50eskosWould it make sense or be possible to have kondo warn on use of for in such a way that the comprehension isn’t actually used? I’m working on a legacy code base and I just fixed an evaluation bug caused effectively by
(defn do-lots-of-things
  [xs]
  (when (a-thing?)
    (for [x xs] (do-more-things x)))
  (when (b-thing?)
    (do-more-stuff)))
That is, because the resulting lazy sequence from that for comprehension isn’t used/returned, it didn’t get evaluated.
#2022-04-0710:42eskos@U04V15CAJ Pinging about this, had a second thought on this today and I think this would fall under the general category of “unused return values”, which probably can be quite a huge category of things on its own, plus I can imagine the implementation would probably get kinda complex as this would require flow analysis. What I’m trying to say, feel free to say “could be nice but nah” 🙂#2022-04-0710:44borkdudeThere's already an issue for "unused return value" and something I've already worked on a bit#2022-04-0710:44borkdudebut it's not yet "there"#2022-04-0710:45borkdudebut returning a lazy sequence isn't wrong, you can't really say that it's unused#2022-04-0711:42eskosNot on its own, of course, in this case the issue is that it’s not in tail position so it gets discarded.#2022-04-0711:43eskosAnd of course that shouldn’t be a generic check either, as sometimes that’s totally fine, especially with eg. do .#2022-04-0711:44eskosEverything’s difficult, anything’s great 🙂#2022-04-0711:44borkdudeah yes, not in tail position, that's a good one#2022-04-0711:52borkdudeWe already to tail position analysis for recur#2022-04-0711:52borkdudeso I guess it would be possible#2022-04-0711:52eskosSounds potentially great 🙂#2022-04-0712:07borkdudeIt would be this issue: https://github.com/clj-kondo/clj-kondo/issues/1258 Feel free to post there#2022-04-0520:27fadrianI was referred here by someone in the general Clojure channel, and I figured Borkdude would know, if anyone did. Is there a library/program for calculating statistics on clojure/script files? I'm thinking about stats like LoC with/without comments, number of functions/macros, depth of expression trees in functions, etc. I looked at clindex, but it didn't seem to give me what I needed.#2022-04-0520:32borkdude@fadrian well, the amount of fns vs macros, etc you can get from the clj-kondo analysis: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md lines of code vs comments, etc you can easily do without any other tools (if you mean ;; comments) expression depths you could do using a tool like tools.reader or edamame which gives you the raw s-expressions and fiddle a bit with that#2022-04-0520:33borkdudeclojure-lsp also has something like call-tree so it is possible to calculate such trees from clj-kondo's analysis as well#2022-04-0520:35borkdudea tool like grasp can help you find certain patterns in clojure code, if that's interesting: https://github.com/borkdude/grasp#2022-04-0520:35borkdudeThis tool uses clj-kondo's analysis extensively to show dependencies between vars: https://github.com/benedekfazekas/morpheus#2022-04-0520:36fadrianThanks. I figured you'd have your finger on the pulse. I was trying to avoid writing more stuff, and grasp looks like a great starting point.#2022-04-0601:25ericdallo@fadrian there is this idea of this new clojure-lsp feature, a dump feature https://github.com/clojure-lsp/clojure-lsp/issues/744 That may not be what you seek yet, but something close to achieve that#2022-04-0611:47fadrianThank you all. I now have some starting points.#2022-04-0616:55sheluchinIs there anything that can help with keywords that either have typos of vary slightly from what's "expected"? These types of bugs have been pretty time consuming on the odd occasion they come up.#2022-04-0617:03pithylessThere's no one solution; but there are at least a couple that tackle the problem with different trade-offs: 1. Validation with eg. malli or spec 2. Autocompletion of keywords in editor when typing 3. Find-references with lsp (so you can see you're using the exact same keyword in other places) 4. Tony Kay tried to avoid this problem to the nth-degree in Fulcro, et al. by making custom namespaced vars for each keyword. Then, you never use the keyword itself, but instead the var (which can be checked at compile time, helps with code navigation, etc.) Example namespace: https://github.com/fulcrologic/fulcro-rad/blob/develop/src/main/com/fulcrologic/rad/form_options.cljc#2022-04-0617:06pithylessI just realized this was posted in #clj-kondo and not #clojure. Hope the advice is still useful, but would be interested to know if there is already something in clj-kondo or lsp that would help with this further.#2022-04-0617:07sheluchinYeah, I like the way RAD options does it as well, @U05476190. Another option is https://github.com/fulcrologic/guardrails, but it creates a fairly significant load in my ETL pipeline, so it has its own tradeoffs. Maybe something like a namespaced keyword whitelist or something might be helpful? Something that defined that :a/x and :a/y are valid, but :a/z is not. At least in some circumstances it would be useful. I am curious as well if there are any considerations towards this problem in clj-kondo.#2022-04-0617:12pithylessI'm actually not sold on the RAD options approach myself, primarily because I'm not convinced it's a big enough problem in my own codebases. But I did want to point it out, since it is a totally legitimate approach if you do find it an annoying problem. :)#2022-04-0617:38borkdudeRight now clj-kondo doesn't have the concept of "I've seen all the files" so it's hard to say whether a keyword is a mistake or not based on the frequency. But if you analyze a whole project and take a look at the keywords analysis you can deduce this yourself. Clojure-lsp however, does have the concept of "seen the whole project" and could maybe help with this somehow based on kondo's keyword analysis.#2022-04-0617:38borkdude\cc @UKFSJSM38#2022-04-0617:40borkdudeOf course with a strict configuration like :a/foo is valid but :a/bar isn't, this would work with clj-kondo#2022-04-0617:56snoe@U05476190 spell-check helps a fair bit too, if you are using full words. A useful lint in lsp, like unused-public-vars, could be single occurrence keywords.#2022-04-0618:01borkdudethat's what I was thinking of#2022-04-0618:01borkdudeperhaps clojure-lsp could just show the frequency of each keyword, similar to vars, or would that be too expensive?#2022-04-0618:01borkdudein lens-mode#2022-04-0618:02borkdudeI never use unused-public-var, the frequency info is sufficient for me#2022-04-0618:04sheluchinSingle occurrence notice sounds like a happy medium. Showing a frequency next to each one might get a little noisy, but some people would probably prefer that configuration.#2022-04-0618:04ericdalloprobably too verbose a lens for that#2022-04-0618:06ericdallobut a custom linter sounds a good POC/try#2022-04-0618:07sheluchinMaybe something along the lines of a single occurrence linter combined with what git does with typos:
$ git logg
git: 'logg' is not a git command. See 'git --help'.

The most similar command is
        log
#2022-04-0618:08ericdalloyes, there are some kondo linters that have a similar feature like refer-all , we could do similar#2022-04-0618:21sheluchinThanks everyone for giving it some thought 🙏#2022-04-0809:22iarenaza@UPWHQK562 In Eastwood you have a linter for that use-case (if I understood you right): https://github.com/jonase/eastwood#keyword-typos#2022-04-0809:26sheluchin@U8T05KBEW interesting. Thanks for the heads up on that. I do not use Eastwood, but interesting nonetheless.#2022-04-0809:32borkdudeMaybe create an issue with references to existing implementations / ideas.#2022-04-0810:00sheluchin@U04V15CAJ indeed, I should. I'll get to that a little later today. Thanks.#2022-04-0917:30sheluchinhttps://github.com/clojure-lsp/clojure-lsp/issues/923#2022-04-0619:35snoeIs there a lint that exists to catch where fn params are probably mixed up. I feel this would help a lot, wdyt?
(defn foo [attrs widget cog] ...)
(foo {} cog thing) ;; lint warn `cog` is passed as arg2 but `cog` is arg3 name
The lint could compare var names passed to a fn with the param names and warn if there's a mixup. It could probably be done with :keys and literals too
(defn foo [{:keys [a b c]} {:keys [d e f]}] ...)
(foo {:d 1} {:a 2}) ;; lint warn `d` is passed to arg1 expecting a,b,c but `d` is expected by arg2 ; warn `a` ...
#2022-04-0619:37borkdudeInteresting, would love to see more real world examples of this#2022-04-0619:37borkdudeHow many times are arguments same-named as the arguments? Not often I assume#2022-04-0619:38dpsuttonin my experience there’s a decently high overlap of named arguments to a function and named arguments in the function declaration#2022-04-0619:38snoeOh I feel it's pretty often, things get passed through, I'll find some examples.#2022-04-0619:42snoeIn clojure-lsp we often pass analysis components or db as the last arguments.
(defn find-last-order-by-project-analysis [pred? analysis db])
(find-last-order-by-project-analysis
    #(= (:name %) (:name element))
    analysis
    db)
If you're not familiar that db comes last you have to confirm by looking at signature it would be easy to accidentally mix up the order and do (find ... db analysis)
#2022-04-0619:43dpsuttonin the metabase codebase we have lots of common things called driver, database, card, etc. And those will be the same for invocation and most likely for the definition#2022-04-0619:43borkdudeMaybe that's just a sign to turn it into a {:db ...} shaped argument?#2022-04-0619:43borkdudeAnd clj-kondo already has "type annotions" for required keys#2022-04-0619:43borkdude#2022-04-0619:44snoehttps://github.com/clj-kondo/clj-kondo/search?q=resolve-cache-dir I dunno, that's an argument that says always use named params..#2022-04-0619:45borkdudeyeah, there's a trade-off. can you make an issue for this and any time you find a real-world OSS example, post it there?#2022-04-0619:49snoeYup, what are you looking for in examples? Existing bugs with this mixup or more evidence that call sites and functions use the same names?#2022-04-0620:04borkdudeThe latter. That you can make bugs with this I believe :)#2022-04-0620:05borkdudeA concept PR is also welcome. I think what should happen more or less: if a symbol call argument matches a fn arg name but the position doesn't match up, it's a warning#2022-04-0620:27snoehttps://github.com/clj-kondo/clj-kondo/issues/1650#2022-04-0620:29snoeI'm not sure if I'll add too many more examples, it's hard to find a function call that doesn't pass at least one var with the same name as an arg.#2022-04-0620:39borkdudeWell, then that's a good indication that we should give this at least a try :)#2022-04-0620:39borkdudeThanks#2022-04-0704:45JasonI've tried running clj-kondo --lint path --dependencies --parallel --copyconfigs --debug in a folder with an existing .clj-kondo/.cache/v1 folder but when I run clj-kondo --lint path --parallel --debug I'm under the impression it isn't using the cache. I do see that timestamps in the cache folder are being updated but it looks like every file in the debug output says Linting file: x and I'm pretty sure I've seen something about skipping files that were already linted in previous runs. I thought the second run should be skipping everything. Am I misunderstanding? Any ideas what is going on?#2022-04-0705:49JasonI think I just misunderstood the point of the cache for clj-kondo, maybe the skip message I saw was when using clojure-lsp. I was trying to figure out an issue with clojure-lsp performance and thought it was due to kondo taking a long time but I'm pretty sure I missed the point.#2022-04-0812:58borkdudeThe cache is not used to skip things, but to remember stuff from previous linting so it can be used to provide richer linting#2022-04-0810:53Jakub Holý (HolyJak)Hi! Is it possible to tell kondo to fail on :deprecated-var in prod code but to ignore it in test code?#2022-04-0810:54borkdude@holyjak You could lint your production code separately from your test code for now, or put a namespace metadata config in the test code.#2022-04-0810:54borkdudeThere is also a configuration to ignore certain deprecated vars in certain namespaces#2022-04-0810:54borkdudesee linters.md#2022-04-0811:00Jakub Holý (HolyJak)Awesome, thanks! > put a namespace metadata config in the test code. Where is that documented? I looked at disabling linters here https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#options but do not see it#2022-04-0811:02borkdudedocumented here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#introduction#2022-04-0811:02borkdude
(ns foo {:clj-kondo/config '{:linters ...}})
#2022-04-0812:36borkdudeclj-kondo v2022.04.08 • https://github.com/clj-kondo/clj-kondo/issues/1331: new linter :non-arg-vec-return-type-hint that warns when a return type hint is not placed on the arg vector (CLJ only). See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#non-arg-vec-return-type-hint. • Enable :namespace-name-mismatch by default • https://github.com/clj-kondo/clj-kondo/pull/1611: support ^:replace override for nested config values • https://github.com/clj-kondo/clj-kondo/issues/1625: Add option --skip-lint, to skip linting while still executing other tasks like copying configuration with --copy-configs. • https://github.com/clj-kondo/clj-kondo/issues/1620: return type too narrow for re-find Analysis: • https://github.com/clj-kondo/clj-kondo/issues/1623: Implement analysis for Java classes: :java-class-definitions and :java-class-usages. See https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md. • https://github.com/clj-kondo/clj-kondo/pull/1635: add :end-row and end-col to analyze data for :namespace-definitionshttps://github.com/clj-kondo/clj-kondo/issues/1651: Improvements for :protocol-implshttps://github.com/clj-kondo/clj-kondo/issues/1612: Improve analysis for deftypehttps://github.com/clj-kondo/clj-kondo/issues/1613: Improve analysis for reifyhttps://github.com/clj-kondo/clj-kondo/issues/1609: keyword analysis for ns + require channel: #clj-kondo#2022-04-0813:18imreWith new linters being regularly added, how do you decide whether to promote something to the warning or error level?#2022-04-0813:31borkdude• For subjective/style things: level :off • Experimental: level :off until further notice • Causes compilation error: level :error • Not wrong, but can cause damage: level :warning #2022-04-0813:31borkdudesomething like that#2022-04-0814:27imreThank you. Just trying to think about a good process of keeping up with all the new rules.#2022-04-0815:24Noah BogartI've opened an issue for keywords in :keys binding vectors (https://github.com/clj-kondo/clj-kondo/issues/1653). There was some chatter about this when I posted about it in February before I went on leave, so seems relevant to bring it up now that I've made the issue.#2022-04-0815:25borkdudeI'm fine with someone implementing that as a stylistic thing which is disabled by default#2022-04-0815:25borkdudeI don't see an urgent need for that check myself and will probably not use it#2022-04-0815:26borkdudeso ... PR welcome! :)#2022-04-0819:24Noah Bogartit's up! thanks for the feedback https://github.com/clj-kondo/clj-kondo/pull/1654#2022-04-0819:44borkdudeThanks! I'll take a look soon#2022-04-0819:44Noah Bogarttake your time simple_smile#2022-04-0815:27Noah Bogartan off-by-default stylistic lint is totally cool with me. Thanks!#2022-04-0819:15nonrecursivehey y’all, I’m having trouble finding docs on an issue. clj-kondo doesn’t appear to be picking up .clj-kondo/config.edn in the deps for a project I’m working on. How would I configure this?#2022-04-0819:16borkdudeHave you tried from the command line?#2022-04-0819:16nonrecursiveI haven’t
#2022-04-0819:16borkdudemaybe try that first#2022-04-0819:20Joshua SuskaloMy first thought with that description of the issue is that your editor is running kondo from the wrong directory.#2022-04-0819:20Joshua SuskaloIf it works from the commandline that makes this theory very likely.#2022-04-0819:21borkdudeThat's why I'm asking that first :)#2022-04-0819:21borkdudeLet's get the editor out of the equation first#2022-04-0819:21borkdudeCould also be an error in the config file#2022-04-0819:22nonrecursiveok I ran
clj-kondo --lint "$(clojure -Spath)" --dependencies --parallel --copy-configs
and then linted a specific file with
clj-kondo --lint src/donut/todo_example/frontend/components/todo_list.cljs
and it’s still showing errors and warnings
#2022-04-0819:23nonrecursivei don’t really use it from the command line so i’m probably doing something wrong? 🙂#2022-04-0819:24borkdude> and it’s still showing errors and warnings so that works right?#2022-04-0819:24nonrecursivesorry, it’s showing errors and warnings, indicating that it’s not loading the .clj-kondo/config.edn files from dependencies#2022-04-0819:25nonrecursivethere shouldn’t be any errors#2022-04-0819:25borkdudeoh, now I get it. clj-kondo does not load .clj-kondo/config.edn from dependencies. when you run with --copy-configs it copies configs from clj-kondo.exports/your-org/your-lib to your .clj-kondo directory#2022-04-0819:26Joshua Suskaloyeah, so dependencies may have kondo configs that they don't export, and may have simplified versions of the configs that they do export to consumers.#2022-04-0819:28borkdudeThat is documented here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2022-04-0819:28nonrecursiveaaaah ok, got it! thanks. have there been any changes around this recently? Up until yesterday or so it seemed like clj-kondo was loading .clj-kondo/config.edn from deps#2022-04-0819:28nonrecursivethank you#2022-04-0819:28borkdudeno, it was always like this#2022-04-0819:29borkdudeNote that you can include the exported config of a lib within that lib's own config using config-paths#2022-04-0819:30nonrecursiveah ok so if a lib has resources/clj-kondo.exports/clj-kondo/my/lib/config.edn then that lib’s .clj-kondo/config.edn can include it?#2022-04-0819:33borkdudeyes#2022-04-0819:33borkdudevia :config-paths ["../resources/clj-kondo.exports/my/lib"]#2022-04-0819:33borkdude(you don't need the extra clj-kondo in there)#2022-04-0819:33nonrecursivegotcha. thank you! I’ll give that a try#2022-04-0819:47nonrecursiveyay it’s working!! thank you :hugging_face: also had to include some -Adev in getting the deps bc my deps.edn needs improvement#2022-04-0819:48borkdude:-D#2022-04-0819:48borkdudecongrats#2022-04-0823:52Noah BogartHow interested would y'all be in a “turn on all lints and make then errors” lint/flag/setting? #2022-04-0906:00DenisMcHi, I’m having a weird problem with my setup which is reducing the value of linting because I’m getting so many spurious errors. I’m using the clojure/java-time library all over the place (using Intellij/Cursive/deps.edn), and it’s working fine in the repl and compiling properly. However, everywhere I use it I get kondo lint errors about functions not being resolvable. For example, if I have something like this:
(ns clj-time-test
  (:require [java-time :as jt]))
(jt/instant)
, Kondo informs me that ‘jt/instant cannot be resolved’ - even though the code works fine and I have java-time in my deps as a dependency. When I look at the java_time.clj namespace itself, I see similar errors. I’m aware that clj-kondo may not be the cause of this problem and it may be flagging some other error in my setup, but maybe someone else has seen this before and could give me a pointer as to what may be causing it because I cannot see anything obvious. Thanks in advance!
#2022-04-0906:10DenisMc…and I just upgraded the clojure-extras plugin, generated stubs and the problem has resolved:slightly_smiling_face:#2022-04-1014:15Joshua SuskaloSo I know very little about this library, but if it uses macros to define its vars, kondo won't pick them up by default. You have to specify in your kondo config how it should treat those macros. For simpler def-style macros this is easy, but for some others it can be a big challenge.#2022-04-1014:18borkdudeWe also have a library here for generating stubs: https://github.com/clj-easy/stub#2022-04-1014:19borkdudeYou can also just disable unresolved-var for some namespaces#2022-04-1118:58Noah Bogarthey michiel, have you thought at all about adding "auto-correct" to clj-kondo?#2022-04-1118:58Noah Bogarti follow the rubocop releases and they flag certain lints as being able to auto-correct issues, and then also flag certain auto-correctable lints as "unsafe" (potentially changing meaning), and then i spent the weekend thinking about how exactly that might be done with clj-kondo lol#2022-04-1119:00borkdudeclj-kondo does not auto-correct issues, but it does give precise locations and information so other tools can be built on top which do so, e.g. clojure-lsp has a ton of stuff#2022-04-1119:00borkdudethis way I can focus on the linting + analysis and don't spend a ton of time on "hey, it doesn't auto-correct correctly, my build is broken" issues#2022-04-1119:01borkdudeanother such tool is https://github.com/oxalorg/clj-konmari/ for example#2022-04-1119:02borkdudehttps://github.com/borkdude/carve is another example#2022-04-1119:04borkdude(more stuff here: https://github.com/clj-kondo/clj-kondo/issues/836)#2022-04-1119:06borkdudeCongrats on your first PR in clj-kondo btw, just merged :)#2022-04-1119:09Noah Bogartthank you! so glad and excited to contribute, which is one of the reasons i've been thinking about this stuff#2022-04-1119:56ericdalloCongrats for the contribution too :) I saw the PR and I always wondered, what is the recommended way? Does clojure style guide mentions that anywhere? I personally prefer not using keywords but I know clj-kondo itself uses a lot that, so not sure it's just a personal preference#2022-04-1119:58Noah Bogartalex miller said that it was originally allowed to handle namespaced keywords but once they got that working with ::keys , it's not the preferred method by the core team, which is good enough for me! i don't think the style guide says anything about it one way or the other#2022-04-1119:59borkdudeI'm fine with abandoning that style forever, now that I'm not working together anymore with someone who did that all over the code base. It's something I got infected by :)#2022-04-1120:03ericdalloNice, good to know#2022-04-1322:37didibusI didn't even know :keys [:a :b] worked. I could swear the spec for defn doesn't allow it/#2022-04-1322:38didibusWow, it does work, and I hate it haha#2022-04-1119:10borkdudeI actually don't use a lot of "auto-correct" stuff myself, usually do it manually#2022-04-1119:10borkdudeexcept maybe renaming a local or so, that's where clojure-lsp really comes in handy#2022-04-1119:53ericdalloYou should try "add missing require" code actions @borkdude is the one I most use for sure :)#2022-04-1119:59Noah Bogartthat one is great, I use it multiple times a day. love to type out (str/join ", ") and then have it added automatically#2022-04-1120:05ericdalloyes, I love more how we can discover and suggest known aliases from ns never required :)#2022-04-1119:57borkdude@ericdallo Nice!#2022-04-1120:03ericdallometal 👿#2022-04-1216:00andrewzhurovIs there an util function that takes an expression of a definition (e.g., (def a (+ 1 1)) and gives body (`[(+ 1 1)]`)?#2022-04-1216:01borkdudein the context of clj-kondo, how would you use that?#2022-04-1216:04andrewzhurovI'm thinking to enrich https://github.com/clj-kondo/clj-kondo/blob/9195cc0f0761a2b673816f5296a95380917ff05b/src/clj_kondo/impl/namespace.clj#L189! with body to have all :vars and their corresponding bodies for playing around with semantics of a program. It's not something that clj-kondo intents to do, but I found reg-var! that is almost what I want. 🙂 (I'd like to have all vars of a program with their vals to later on derive one big val without vars) (sounds crazy, yeah)#2022-04-1216:06andrewzhurovSo I thought, in order to derive body out of a def expr perhaps there is an utility function#2022-04-1216:44andrewzhurovfound how to do https://github.com/clj-kondo/clj-kondo/blob/9195cc0f0761a2b673816f5296a95380917ff05b/src/clj_kondo/impl/analyzer.clj#L1005 body>, but don't know how to any def expr -> body so far#2022-04-1217:17andrewzhurov;; TLDR no worries, I've got it. 😄 seems there is no such function, I see analysis functions for different def exprs parse it one child at a time e.g., in https://github.com/clj-kondo/clj-kondo/blob/9195cc0f0761a2b673816f5296a95380917ff05b/src/clj_kondo/impl/analyzer.clj#L502 e.g., in https://github.com/clj-kondo/clj-kondo/blob/9195cc0f0761a2b673816f5296a95380917ff05b/src/clj_kondo/impl/analyzer.clj#L1035 I'm interested only in those atm and will tweak them to pass into reg-var! :body as well#2022-04-1216:41rgmI'm just dipping my toes into hooks and I want to figure it out with the repl. Are there any tricks I should know about in turning my code into a rewrite-clj node to feed it in for playing around, or is there another/better way that people test hooks?#2022-04-1216:58rgmI've got the (prn ,,,) working to give feedback from a command-line linter run, but was wondering if there's a good way to test them from eg. a (comment (my-hook ,,,)) block. Is making a fn rewrite-clj node -> rewrite-clj node all there is to it?#2022-04-1217:05rgmhm just re-read https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#debugging and I guess this'll do for now, since the linting run is so fast#2022-04-1220:39imreI asked something similar a while back, perhaps it hekps https://clojurians.slack.com/archives/CHY97NXE2/p1644324979611669?thread_ts=1644324979.611669&amp;cid=CHY97NXE2#2022-04-1316:12rgmoh that does help, thank you. So far I'd been trying to thin down my hook code to just call a function, return a very obvious map eg. {:new-let-binding-vec [,,,]} and do only very obviously correct stuff in the hook. Then I can work on the function someplace else and paste it back in.#2022-04-1316:12rgm(which is probably not a bad strategy for anything, tbh).#2022-04-1220:23dviramontesis it possible to specify a list of source paths for clj-kondo to lint against ? (aka src, test, shared-src, etc) in the ./clj-kondo/config.edn ?#2022-04-1220:24borkdude@dviramontes not in config.edn, these are arguments to either the CLI or JVM lib:
--lint src:test:shared-src
#2022-04-1220:24dviramontesnbd, thank you!#2022-04-1408:21Teemu KaukorantaHello! Is there a way to print the final configuration that clj-kondo uses? Or is there a sample config.edn somewhere with all the default values?#2022-04-1408:32borkdudeThis default is in clj-kondo’s repo in impl/config.clj. Also see linters.md for all linters + defaults.#2022-04-1408:33Teemu KaukorantaExcellent, thank you.#2022-04-1411:54Teemu KaukorantaIs this a typo? https://github.com/clj-kondo/clj-kondo/blob/320ee3f3c158b66eed36dcbc314fbd70b47ed9e2/src/clj_kondo/impl/config.clj#L45= Should :simple-libspec be inside the map?#2022-04-1411:56borkdudeyes#2022-04-1412:01borkdudePR welcome#2022-04-1412:12Teemu Kaukorantahttps://github.com/clj-kondo/clj-kondo/pull/1656#2022-04-1412:24borkdudethanks#2022-04-1413:36Noah BogartHas any thought been given to separating "parsing the code to an AST" and "linting the code"? I noticed that they're intertwined currently.#2022-04-1413:37Noah Bogarti would be willing to help out if this is desirable#2022-04-1413:40borkdudeIt's intertwined for performance, everything can be done in a single pass#2022-04-1413:42Noah Bogarti had a feeling that was the case. have you experimented at all with separating them into two passes? Does that degrade performance by a lot?#2022-04-1413:43borkdudeThe rewrite-clj stuff is already the AST#2022-04-1413:44borkdudewhen I initially wrote clj-kondo I had multiple passes and discoverered that a single pass was much better for fast responses#2022-04-1413:44Noah Bogartyes but you have done a lot of good work adding relevant data to the naive ast#2022-04-1413:44borkdudeI would rather not refactor for "beauty" but to solve a real problem#2022-04-1413:47borkdudemany linters still need the raw rewrite-clj nodes#2022-04-1413:49borkdudeif you are looking for stuff to help with, take a look at the project: https://github.com/clj-kondo/clj-kondo/projects/1#2022-04-1413:51Noah BogartI was more thinking about ways to make lints standalone: an object or function that can be registered as working on some ast form, so that if i wanted to write a new lint, I wouldn't have to dig through the code to find the one spot where clj-kondo handles that ast, i could just say something like:
(reg-linter! {:ast-nodes [clojure.core/cond] :name :even-forms :lint-fn (fn [ctx bv] (odd? (count (:children bv)))})
or something similar
#2022-04-1413:52Noah Bogartoh cool, i haven't seen that project page. i'll take a look, see if there's anything i can help with#2022-04-1413:56Noah Bogartmy thought with bringing all of this up is that if the barrier for entry is lower, more people might contribute new lints (like I did recently), which I think is a net good overall#2022-04-1414:35borkdudeThere's also this sorting of issues: https://github.com/clj-kondo/clj-kondo/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc#2022-04-1416:07lreadI continue to have major ❤️ for clj-kondo. I just upgraded to the newest version and a new linter said, “Hey, buddy, this looks a little off, maybe?”
src/rewrite_clj/reader.cljc:242:11: warning: Prefer placing return type hint on arg vector: Closeable
linting took 4710ms, errors: 0, warnings: 1
#2022-04-1509:42borkdude😅 https://github.com/babashka/fs/commit/dc73460e63ff10c701c353227f2689b3d7c33a43#2022-04-1515:53lreadGotta love it when your own tools help you out! So cool!#2022-04-1517:04lreadJust bumped clj-kondo for cljdoc: https://github.com/cljdoc/cljdoc/commit/50aa3f88163256068cdbca259f12492c94ebb4bf#2022-04-1522:18dviramontesWith clj-kondo analysis export capabilities, is it possible to get at this information here to get the number of errors found after linting ?
linting took 3272ms, errors: 41, warnings: 806
#2022-04-1522:18dviramontesin other words, is there a way to export this linting result data ?#2022-04-1522:20borkdudeYes:
user=> (:summary (with-in-str "(+ :inc)" (clj-kondo/run! {:lint ["-"]})))
{:error 0, :warning 1, :info 0, :type :summary, :duration 12, :files 1}
#2022-04-1522:21dviramontesAmazing thank you!#2022-04-1710:33mike_ananevWith the latest clj-kondo v2022.04.08 I’ve got false positive Unused import.
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "d0bdb9bbb590bdb2a0e0e2"}, :content ("[email protected]")}
Repo with source codes is here: https://github.com/redstarssystems/gost
#2022-04-1720:32borkdudeCan you create a clj-kondo issue with a minimal repro?#2022-04-1721:15mike_ananevyes, I can.#2022-04-1813:29borkdudethanks#2022-04-1813:34borkdudecreated it here: https://github.com/clj-kondo/clj-kondo/issues/1659#2022-04-1820:27mike_ananevSorry. I wanted to create issue today’s evening, after my day work. Thank you.#2022-04-1717:01craftybonesHello. I just moved to an M1. I’m having some trouble getting the clj-kondo server started on Calva#2022-04-1717:01craftybonesIt seems to not find my java runtime. I am not sure where or how#2022-04-1717:11craftybonesFriggin! No default runtime on the m1! Totally forgot#2022-04-1717:19craftybonesGrrr. Got it working. Had to install openjdk#2022-04-1717:19craftybonesHopefully there aren’t other errors#2022-04-1802:56rayattldr: Can I manually perform the command myself, since it doesn't appear to be working for me? Hi, I installed crypticbutter/snoophttps://github.com/CrypticButter/snoop/tree/main/resources/clj-kondo.exports/com.crypticbutter/snoop. I tried running the --copy-config command, yet nothing happens - it waits a long while, before printing nothing. I've got a monorepo with nested/inherited kondo configs, so I wondered if the dir at which I ran the command from the docs (`clj-kondo --copy-configs --dependencies --lint "$(clojure -Spath)"`) mattered, though it doesn't seem to matter. The 3 requirements listed in the docs (--deps flag, --copy flag and presence of .clj-kondo folder) are met. I'm using Calva, so my understanding is that it's supposed to do that sort of thing for me anyways? Not sure, as that doesn't appear to be happening either. In any case, it doesn't appear that any config was copied over (whether newly created files or inline'd somehow into existing config files, which I don't think is how it's supposed to work anyways). I checked my user kondo config as well just in case - no dice. What are my options? Anything I can provide to help debug?#2022-04-1813:28borkdude@rayatrahman9 Yes, you can manually execute --copy-configs. After that you should have the configs in .clj-kondo/<somewhere>#2022-04-1816:03rayatApologies, I meant, manually perform whatever work is being done with that command myself, eg copying files and such. Running the command with, for example, --skip-lint, doesn't work either#2022-04-1816:06borkdudeare you using the correct version of that library which has the config bundled?#2022-04-1816:06borkdudeI'd rather have you debug the root cause than work around it#2022-04-1816:06borkdudebut you can always copy the config manually, sure#2022-04-1816:06borkdudejust clone the repo and do it#2022-04-1816:11rayatThanks! I think so? It's the version on clojars that is the latest master as well. What do I copy? The folder with the config.edn or the folder within that with the hooks? And what folder hierarchy would it be?
.clj-kondo/clj_kondo/crypticbutter/snoop.clj
https://github.com/CrypticButter/snoop/tree/main/resources/clj-kondo.exports/com.crypticbutter/snoop supposed to be copied as well, or its content inlined into my existing config that I have in that .clj-kondo folder?
#2022-04-1816:12borkdudedocs over here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2022-04-1816:13borkdudewhat you were saying is correct#2022-04-1816:13borkdudeeverything under clj-kondo.exports should be copied into your .clj-kondo dir as is#2022-04-1816:13borkdudethat is exactly what --copy-configs does#2022-04-1816:14borkdudeif I were you would I check the contents of the .jar file you are using as a dependency#2022-04-1816:14borkdudeif the config is there#2022-04-1816:14borkdudecheck, don't just assume#2022-04-1903:34rayatNo kidding, your spidey senses are better than mine, indeed the version on master was not published#2022-04-2100:02Asko NōmmWhenever I open VSCode + Calva on a project, I get a bunch of warnings like this from kondo, however when I click on them, they disappear, because turns out there’s actually nothing wrong. I’ve tried deleting the .clj-kondo, .lsp, and .calva directories, but the issue persists each time. Any thoughts?#2022-04-2100:36bringeDo you still have this problem after reloading the window? I wonder if there was some issue with stale clojure-lsp data. I’m guessing you reloaded the window after deleting those directories, though, right?#2022-04-2100:37bringeYou can also stop and start clojure-lsp from the command palette, or click the button in the status bar to do so. I don’t know if that would help though.#2022-04-2100:49Asko NōmmYup, reloaded window, restarted VS Code, but the problem stays 😞#2022-04-2101:15Asko NōmmOk managed to find out why! Apparently I had src/ files in target/ (no idea how that happened) which was causing this. Fixed!#2022-04-2312:43borkdudeI have a working title for "discouraged var", for configuring vars that you'd rather not use in your program (think eval, read-string, whatever). Any alternative names?#2022-04-2313:50Noah BogartDiscourage, deny, disallow, exclude, reject, block#2022-04-2314:06borkdudeI'll stay with discouraged then#2022-04-2314:11Noah BogartI think that's the best choice too #2022-04-2314:25borkdude
$ clojure -M:clj-kondo/dev --lint - --config '{:linters {:discouraged-var {clojure.core/inc {:message "Incrementing numbers is dangerous"}}}}' <<< '(inc 1)'
<stdin>:1:1: warning: Incrementing numbers is dangerous
#2022-04-2314:40Noah BogartWill there be a default message? #2022-04-2314:55borkdudeyes:#2022-04-2314:55Noah BogartThat’s beautiful. Thank you so much#2022-04-2314:58borkdudeDiscouraged var preview: https://twitter.com/borkdude/status/1517880266840285184#2022-04-2320:52borkdudeclj-kondo v2022.04.23 • https://github.com/clj-kondo/clj-kondo/issues/1653: new linter :keyword-binding - warns when a keyword is used in a :keys binding vector. This linter is :off by default. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#keyword-in-binding-vector. • https://github.com/clj-kondo/clj-kondo/issues/996: new linter :discouraged-var. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#discouraged-var. • https://github.com/clj-kondo/clj-kondo/issues/1618: new :config-in-ns configuration option. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#config-in-ns. • Support :ns-groups configuration option. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#namespace-groupshttps://github.com/clj-kondo/clj-kondo/issues/1657: support bindings with same name in clojure.core.matchhttps://github.com/clj-kondo/clj-kondo/issues/1659: fix false positive unused import • https://github.com/clj-kondo/clj-kondo/issues/1649: dot (`.`) should be unresolved when not in fn position#2022-04-2400:04nateThank you for :config-in-ns! This will help a lot!#2022-04-2405:53rayatI want to try to write a custom hook for the helix/defnc macro. Specifically, I want it to behave almost completely like a regular defn, except for a single thing: • In a specific place in the macro, I want to teach clj-kondo to treat a particular form as a thread-first chain. • It's not a macro or fn call that I can ":lint-as ->", it's more like a map like {:to-be-threaded [ (foo "2nd arg") (bar "2nd arg" "3rd arg") ]} Deets: • There's a special key (`:wrap`) in a kinda-metadata map basically, whose value is a vector of function calls, each of which, when defnc is expanded, have their first arg passed in via an emitted thread-first chain. • Kondo does not know statically that these function calls will eventually make sense when they're threaded, so it yells invalid-arity at me. • While we could ignore kondo in these cases (somehow? I don't even know how to do that either), it would be sick to preserve arity checking, just accounting for/ignoring just the first arg.
;; usage example

(defnc function-component-name 
  [props another-param]
  {:wrap [(hoc-fn "baz")]} ;; this guy here, a special "arg" after the "actual" arg vector
  <...body...>)

;; where the fn named hoc-fn above could be:
(defn hoc-fn 
  [component baz] 
  <...body...>)

;; macroexpanded output of "this guy here" bit somewhere within `defnc`'s expansion
(-> some-inner-component
    (hoc-fn "baz"))
If I wrote a custom hook, would I be able to just mirror default vanilla defn linting, except at that specific map key? If so, how do I ensure I've got the right node at which the :wrap key is? • I don't want to accidentally apply this special linting to the actual arg vector, in case there's a key in an map there with the same name • etc Thanks!
#2022-04-2407:22borkdudeMaybe it helps to look at a couple of examples? https://github.com/clj-kondo/clj-kondo/discussions/1528#2022-04-2407:24borkdude> If so, how do I ensure I've got the right node at which the :wrap key is? You basically have to do that parsing yourself: first find the child that is after the vector, if it's a map then do your special thing, etc#2022-04-2413:43Noah BogartIs function-component-name supposed to be the same as some-inner-component?#2022-04-2413:43Noah BogartMaybe share a small real code example #2022-04-2419:10rayat@UEENNMX0T technically no? some-inner-component is more or less an inline (fn [args] body), which after being threaded through the higher order functions (in my example just hoc-fn), is returned by defnc, and bound to the name function-component-name I was thinking of posting real ish code, but didn't want to noise it up for those unfamiliar with helix. I'll post in a sec. Thanks for helping out guys!!!!#2022-04-2419:37rayatReal-life-ish code examples
(defn hoc-fn [component-fn] ($ component-fn)) 
In the following snippet, there are 2 lines with comments saying "example" Those are both cases of calls to functions that expect at least one argument, but when used here, we leave that out, as the macro defnc will take care of that for us.
;; usage of defnc
(defnc textbox
  [{:keys [class value title] :as props} ref]
  {:wrap [(react/forwardRef) ;; example
          (hoc-fn)]}         ;; example
  (d/input
    {:ref ref
     :type "text"
     :auto-complete "chrome-off"
     :class (cx textbox-style class)
     :on-change (when on-change #(on-change (.. % -target -value) %))
     & (dissoc props :class :on-change)}
    children))
Helix's impl of
(defmacro defnc
   "docstrings here"

;; ... a bunch of stuff mostly unrelated...

;; then, near the end of the implementation of `defnc`, 
;; (removed nesting whitespace here)

(def ~(vary-meta
                component-var-name
                merge
                {:helix/component? true})
           
#2022-04-2500:38rayathey @U04V15CAJ, I'm trying to use :macroexpand hooks for the above now. IE., :hooks {: macroexpand { helix.core/defnc hooks.helix.core/defnc }}. I've got (more or less) a copy-pasta of the source code of the helix.core/defnc macro in /.clj-kondo/hooks/helix/core.clj 1. From reading the hooks.md, I'm under the impression that what this type of hook does, is tell kondo/sci what to expand the macro to when it sees in the wild. a. Therefore, if I literally just copy the original (defmacro defnc ...) verbatim from helix's source code, b. Except for inlining imports or removing bits of code that don't affect my desired thing (the :wrap threading) etc, c. Should it "just work"? i. (Minus any typos or lil mistakes on my end of course) d. Or have I completely misunderstood what :macroexpand hooks do? 2. How do I debug or ascertain that kondo is even "picking up" or "registering" that I've set a hook for defnc? a. I placed a couple of prn statements and whatnot, and then ran clj-kondo --lint on a few files b. But I see neither the prn statements nor has anything changed from before I defined this hook 3. Does it matter that I'm in cljs? Thanks again for your time and help!#2022-04-2518:09Noah Bogartokay, i read through the code and i don't understand it at all lol. i was hoping i could help out but this macro is... way too complex for me#2022-04-2518:12borkdudeAt 2: if you don't see the prn output then it's probably not configured correctly. As with debugging anything, dumb down the example to something more trivial and try again#2022-04-2518:13Noah Bogartmake sure you're running clj-kondo --debug in addition to whatever else you do#2022-04-2518:13Noah Bogartclj-kondo --debug --lint path/to/file#2022-04-2518:14borkdudeAt 1: macroexpand is similar to analyze-call but works directly on s-expressions, that's the only difference. for debugging, inspect the return value from the macro using prn and see if looks correct#2022-04-2518:14borkdudeAt 3: probably not#2022-04-2503:29rayatOn the topic of writing clj-kondo hooks (ie analyze-call), the debugging instructions in hooks.md suggests using prn statements. So the idea is that if I were to manually run clj-kondo from the cli - to lint some file that I know makes use of the macro I'm writing the hook for - I should see those prn statements in the command line alongside whatever linting results for the file (`eg linting took 57ms, errors: 1, warnings: 5`), right? If so, I do not see the print statements - how can I debug if I config'd it incorrectly?#2022-04-2506:22DumchI wasn't able to get it to work either, so I was just throwing errors to see the data 🙂 Subscribing to the thread.#2022-04-2506:54borkdudeIf you don't see any output then simplify your example until you do see output and then go from there.#2022-04-2507:49Dumchthanks 🙂#2022-04-2507:51DumchAnd previously I did evertything without terminal, used to see results only in diagnostics#2022-04-2507:51borkdudeterminal is easier#2022-04-2507:51Dumchyes, I see now#2022-04-2507:52DumchMay be docs "workflow" section would be helpful#2022-04-2507:53borkdudegood point#2022-04-2507:53borkdudeI've written something here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#debugging But it may not be obvious that testing from the terminal is what is implied here#2022-04-2507:53borkdudeHow else are you going to see those printlns#2022-04-2507:56DumchI also spent like half an hour trying to debug it with repl and googling for help, then surrendered#2022-04-2516:44rayatI wasn't sure at all myself what was implied - I know for sure that there are many non standard workflows in the clojure/lisp/repl world thus I do not know what I do not know, and in this case, it is not so obvious if the answer to my question was either: 1. I made a mistake in the execution of my work/code within my hook, so I'll simplify my hook until it prints and then go from there 2. OR I made a mistake in my understanding of the workflow itself, or messed up config or namespacing or something I'm still new to, so no amount of simplifying my hook would help, as the issue was somewhere else unknown to me#2022-12-0412:32Dumch@U037TPXKBGS, I just checked out the new https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#developing-hooks-in-the-repl and it is amazing. I end up adding an alias in my deps.edn:
:clj-kondo
  {:extra-deps {clj-kondo/clj-kondo {:mvn/version "LATEST"}}}
And run a repl like: clj -M:nrepl:clj-kondo
#2022-04-2516:15DumchDon't know if it's a bug or I do not know somehting. One (1) way linter works with nvim-lsp-config and command line, another (2) it works only in command line. 1. I get node directly from children and then pass it to let body. 2. I get node from children, do sexp on it, then convert it back to node (result is the same in print). here is a screen for 1:#2022-04-2516:15DumchMy function looks like:
...
(prn :key2 key2)            ;=> :key <token: bob> 
(prn :key (token-node key)) ;=> :key <token: bob>
...
{:node <here a let form like:
 (let [name1 value1 ... name-n value-n]
    key2 ;; key2 works, (token-node key) does't work
    body-node)>}
#2022-04-2516:16Dumchby 'working in command line" I mean it prints error as expected for both key2 and (token-node key) varians#2022-04-2516:19borkdudeIf it works on the command line then it's likely that your editor doesn't use the same version of clj-kondo#2022-04-2516:19borkdudeor the locations aren't being set properly in the error#2022-04-2519:23ericdalloWe probably found the issue, hook is missing meta data: https://clojurians.slack.com/archives/C03A6GE8D32/p1650914391109129?thread_ts=1650669838.842329&amp;cid=C03A6GE8D32#2022-04-2519:24borkdudeyep, that's what I thought ;) > or the locations aren't being set properly in the error#2022-04-2621:50jacob.maineIs it possible to turn off analysis of :var-usages? If not, and that feature were added, could I expect it to speed up analysis? That is, if analysis were limited to :namespace-definitions, :namespace-usages, and :var-definitions, would it be much faster, or is analysis more dominated by other things like parsing the file?#2022-04-2621:51borkdude@jacob.maine You could test that by manually disabling. I expect it not to matter much#2022-04-2621:52borkdudeWhat is the context of the question, clojure-lsp?#2022-04-2622:01ericdalloBut does kondo already support disable only var-usages?#2022-04-2622:01jacob.maineAh, so it can already be disabled? Cool. I’ll try that. Yes, I’m asking for clojure-lsp. I’m contemplating a different startup strategy. The strategy would improve startup time in large projects and on initial load of new projects. Instead of doing a full analysis of the whole project and all its deps, we would only analyze the open files. That would work better if we could also analyze files one step away (required namespaces, or namespaces that require the open namespace), which we’d need to do an initial analysis of :namespace-definitions and :namespace-usages for. By itself, with a little bit of clever caching and on-demand analysis, that’d give us enough information to support must clojure-lsp features. There are a few more we could support if the initial analysis included :var-definitions#2022-04-2622:02borkdude> Ah, so it can already be disabled? No I meant, testing it by disabling it manually in the code#2022-04-2622:17jacob.mainei guess i should phrase my question slightly differently… if we could skip analysis of def and defn bodies (except to get var names, and maybe arglists and other metadata), would you expect that to speed up analysis?#2022-04-2622:22borkdudepotentially yes. there might be some unexpected interactions with hooks though, I think those should be always fully expanded first and then the bodies could be ignored after those#2022-04-2622:22borkdudeagain you can try this out by manually disabling some code and see the difference#2022-04-2622:25jacob.maineok, thanks. i’ll try it sometime. obviously short-circuiting would omit vars defined within another defn, and other such monstrosities, but i think we could live with that.#2022-04-2700:47jacob.maineIt takes 713ms (measured by criterium) to analyze (and lint) src/clj_kondo/impl/analyzer.clj itself, with a more-or-less default config. With var-usages disabled, it takes 550ms. It takes 2740ms to analyze all of src/clj_kondo/, and 1955ms with var-usages disabled. That’s 23% and 29% faster, respectively, a modest but somewhat surprising amount. I didn’t expect it to change that much since it’s still doing all the work to find var-usages, just skipping the call to reg-var-usage!. Skipping analysis of def(n) bodies is a more dramatic improvement. 107ms for analyzer.clj and 514ms for src/clj_kondo/, 85% and 81% faster than baseline. I didn’t go to the trouble of turning off any of the linters, though many of them don’t make sense if you don’t analyze var-usages. In quick tests, turning off linters reduces the size of the :findings, but doesn’t decrease overall time much.#2022-04-2707:47borkdude@U07M2C8TT That's quite significant. Let's talk in #clj-kondo-dev for further details#2022-04-2705:34HukkaIs there a way to make kondo use namespace aliases as the key for sorting the requires?#2022-04-2707:47borkdudeI'm not sure what you mean with this#2022-04-2707:52HukkaSo for example
(ns mynamespace
  (:require
    [cljs-http.client :as http]
    [com.fulcrologic.fulcro.dom :as fulcro.dom]
    ))
is how kondo would like them to be, since cljs-http comes before com. But in longer lists that makes it harder to see where the alias is coming from, have to use search. So the option would be to have it sorted by the alias; fulcro before http.
#2022-04-2707:53borkdudeThe reason this isn't supported is that tooling like clj-refactor and clojure-lsp do not respect custom sorting rules#2022-04-2707:58HukkaHm, ok#2022-04-2720:15dpsuttonI’m seeing cljs.core/clj->js is called with 3 args but expects 1 [invalid arity] in emacs. I tried to reproduce this with clj-kondo from the command line and cannot reproduce though.
❯ echo "(clj->js [1 2] :keyword-fn name)" | clj-kondo --lang cljs --lint -
linting took 115ms, errors: 0, warnings: 0
I’m confused about this discrepancy as i don’t think clojure-lsp would falsely say this because it relies on clj-kondo’s analysis?
#2022-04-2720:16borkdudeare you running that in the same project?#2022-04-2720:17dpsuttonno from /tmp didn’t think project would matter. let me check#2022-04-2720:17dpsuttoninteresting!
metabase on  master [$?] via :coffee: v17.30 on :cloud:  metabase-query
❯ echo "(clj->js [1 2] :keyword-fn name)" | clj-kondo --lang cljs --lint -
<stdin>:1:1: error: cljs.core/clj->js is called with 3 args but expects 1
linting took 175ms, errors: 1, warnings: 0
#2022-04-2720:17borkdudeyes, that matters, if there is some other version of clojurescript in your dependencies, then it may have picked up on that#2022-04-2720:18dpsuttonwe don’t declare a version of clojurescript. we run shadow-cljs from the command line which brings in its own version#2022-04-2720:19borkdudeIt seems the arity was changed 5 years ago: https://github.com/clojure/clojurescript/commit/e3a9f0cd8511dcfe0c80f37834b5aa32c7b058d4#2022-04-2720:19borkdudeit could be that clojurescript is being brought in via one of your dependencies, an ancient one#2022-04-2720:20dpsuttonpattern not found in clj -X:deps tree Is there some fallback version kondo uses?#2022-04-2720:20dpsuttonwe have lots of exclusions in deps.edn. and nothing brings it in. the version depends on the ambient shadow-cljs used#2022-04-2720:21dpsuttonspecified in package.json: “shadow-cljs”: “2.11.20",#2022-04-2720:21borkdudeclj-kondo uses a fairly recent version of clojurescript as the built in one#2022-04-2720:22borkdudeyou could try to wipe your .clj-kondo/.cache and .clojure-lsp/.cache#2022-04-2720:22borkdudeand then see if it comes back#2022-04-2720:22borkdudebe sure to execute lsp-workspace-restart#2022-04-2720:23borkdudeif it comes back, my only logical explanation would be that there is an ancient CLJS version on your lsp classpath somewhere#2022-04-2720:23dpsuttonkilled the cache and its now reporting fine#2022-04-2720:23dpsuttonweird. i don’t know how it would have gotten into this state#2022-04-2720:23borkdudedo you have any .lsp/config.edn config in this project?#2022-04-2720:24borkdudeyes you have#2022-04-2720:24borkdudeit uses this classpath:
"clojure" "-A:dev:ee:ee-dev:drivers:drivers-dev" "-Spath
#2022-04-2720:24borkdudeso I'd take a look in there#2022-04-2720:24dpsuttonyes. its just the metabase repo. It was reporting the errors from hsql. not sure how that state got there#2022-04-2720:24dpsuttoni’m still not clear on when clj-kondo is aware of deps and not#2022-04-2720:25borkdudewell, it is aware of dependencies that it has linted#2022-04-2720:25borkdudeand lsp calls clj-kondo on your project dependencies#2022-04-2720:25borkdudeor the classpath you have configured in .lsp/config.edn#2022-04-2720:27borkdude"reporting the errors from hsql"?#2022-04-2720:29dpsuttonyeah. i can’t recreate it after deleting the cache. sometimes it is aware of honeysql and complains about some macros from there#2022-04-2800:01ericdalloI already say this behavior, but never managed to reproduce, it's pretty rare and usually happens on complex projects, but I have a guess it's related to kondo cache, erasing LSP cache just make we re-scan everything which makes clj-kondo repopulate cache, next time, we can try removing kondo cache first#2022-04-2721:16nottmeyHi, clj-kondo doesn’t seem to understand deftest- :thinking_face:#2022-04-2721:17nottmeyNote: Maybe it is confused, because I have this under the src folder#2022-04-2721:17nottmeyHow do I resolve this?#2022-04-2721:19borkdudeThat's interesting. I've never heard of deftest- but you can solve it with:
{:lint-as {clojure.test/deftest-i clojure.test/deftest}}
#2022-04-2721:20borkdudeAnd an issue is also welcome#2022-04-2721:46nottmeyOk, thanks, will do ☺️#2022-04-2722:25nottmeyfyi https://github.com/clj-kondo/clj-kondo/issues/1672#2022-04-2721:17Noah BogartOpened this feature request issue: https://github.com/clj-kondo/clj-kondo/issues/1671. As I said in it, I would be willing to write the lint.#2022-04-2721:23borkdudeThis has never happened to me before, but probably because I don't use a lot of pre/post :)#2022-04-2722:02Noah BogartIt’s never happened to me either but I've now found it in 3 places in my job's codebase so it seemed worthwhile to add#2022-04-2722:05borkdudeI always wonder with issues like this if they can be more general#2022-04-2722:06borkdudee.g. (and (number? x) (odd? x) (number? x)) seems a similar case#2022-04-2722:49Noah BogartThat’s a great point. If you're interested I'm willing to write it up, but no worries if you're not#2022-04-2800:03ericdalloredundant-check lint#2022-04-2807:49borkdudeyes, or redundant-condition or so#2022-04-2809:12dominicmWhat if the check is non-pure?#2022-04-2809:20borkdude@U09LZR36F that is a very good point#2022-04-2809:26borkdudeso I'm reluctant to support this linter as it doesn't seem that important to me and it could possibly lead to false positives#2022-04-2812:25ericdallomaybe support it for just core stuff or things that should not have side effect?#2022-04-2812:27borkdudeI reacted on the issue. I don't think this is important enough to justify the effort#2022-04-2812:29borkdudeif you really still want to find duplicates in your code, you can use grasp. I'll give a link later today#2022-04-2812:30dominicmGrasp-powered custom linters?#2022-04-2812:32borkdudehttps://github.com/borkdude/grasp#2022-04-2812:33borkdudeyou could also implement a hook on defn to implement the linter yourself#2022-04-2812:37Noah BogartCool#2022-04-2812:39borkdudeNo is temporary though, if more users request this, might change.#2022-04-2812:39borkdudeyou can leave the issue open if you want#2022-04-2812:40Noah BogartWill do! I like writing these things so if others end up wanting it, I’ll still be willing to do it#2022-04-2801:13Noah BogartHere’s a silly related idea that I'm strangely intrigued by. How would you feel about a style lint that checks https://en.wikipedia.org/wiki/De_Morgan's_laws? So, nested ands and ors flagging a warning if they could be reduced/combined (with the error recommending the reduction)#2022-04-2813:05Noah BogartIf I write a hook for a core function, it won't overwrite built-in lints for the function, right? I only have experience writing hooks for custom functions so I’m not sure how these things work together#2022-04-2813:09borkdude@nbtheduke You can build a hook for a core function and return nil in the hook, then the core linter will still run#2022-04-2813:26DenisMcQuick question: are there good reasons for or against adding .clj-kondo to .gitignore? I currently don’t share clj-kondo config in my projects, but I just realised I don’t understand why I don’t share this config.#2022-04-2813:28imreI think sharing it is a way to communicate what you expect from code added to the repo#2022-04-2813:28imrelike, you expect required namespaces sorted etc#2022-04-2813:29DenisMcYa that's what I'm thinking, it's better to share it. #2022-04-2813:29imreI normally add .clj-kondo/*/ to gitignore, that makes the cache and any copied configs not be checked in#2022-04-2813:32DumchIn my projects I now have:
.clj-kondo/*
!.clj-kondo/config.edn
!.clj-kondo/hooks/
#2022-04-2813:36DenisMcI'm curious: would you not share copied configs? For example, our project uses slingshot which has custom config. If I was to exclude that then all other developers would have to manually set up the custom config themselves to clear those errors.#2022-04-2813:39imreI've been debating that, but since an early step in our CI is to analyze deps with --copy-configs and we usually also have that as a bb or just command in every repo, I don't really see the point#2022-04-2813:39imreif a dev uses kondo, they'll know how to lint deps with copy configs#2022-04-2813:39imreand this way we save some churn that might happen when an updated dependency brings in a new config#2022-04-2813:41DenisMcOk, makes sense. I haven't added code analysis to our CI pipeline yet (still early stages), and I can see how that would help plug that particular gap in a different way. Thanks for the insight. #2022-04-2813:46imreI have seen @borkdude recommend checking these in though, so I'm a bit on the fence about it#2022-04-2815:02borkdudeAll files in .clj-kondo I check into source control except .cache#2022-04-2815:02borkdudeThe reason is that everyone working on the same code, including CI, gets to see the same config#2022-04-2815:04imreDo you have a step to check that imported configs are in sync between the .clj-kondo folder vs their publishing libraries?#2022-04-2817:56snoeHi @borkdude, I've recently joined metabase and I think this is not possible, but I wanted to run it by you. As it stands, functions marked with :hydrate or :batched-hydrate metadata seem to be unused but are, in fact, invoked by calls to toucan.hydrate/hydrate. On the flip side, from calls to hydrate finding the function definition can be difficult. Registration: - https://github.com/metabase/metabase/blob/master/src/metabase/api/permissions.clj#L84 - https://github.com/metabase/metabase/blob/master/src/metabase/models/permissions_group.clj#L111 Usage: - https://github.com/metabase/metabase/blob/master/src/metabase/api/permissions.clj#L109 - https://github.com/metabase/metabase/blob/master/src/metabase/api/permissions.clj#L116 I would like to: 1) hook into clojure.core/defn to reg-keyword! the hydration key. - I'm not sure what would happen if I tried to hook defn, I suspect bad, recursive things? 2) hook into toucan.hydrate/hydrate to register a usage of the defn var (`add-member-counts & members` in the example) based on the keyword used. - I think ns-analysis is insufficient as I do not know in which namespaces the functions with :hydrate are defined. It'd be nice if it was possible to create hooks for these without code changes, but I suspect I will need something like re-frame's reg-sub to wrap the registration and give kondo a seam?#2022-04-2818:06borkdude> I'm not sure what would happen if I tried to hook defn, I suspect bad, recursive things? This is possible. It's currently not possible to use more than one hook per function though, there can be only one (again, currently). > toucan.hydrate/hydrate If the name of the keyword uniquely defines the name of the var, you could expand that call into an explicit call which makes the var usage visible to clj-kondo.#2022-04-2819:14snoeI thought about this, but unfortunately it's common for them to differ. The 2nd registration example shows var add-member-counts is registered as the :member_count key#2022-04-2818:10borkdude@snoe There is now a new :context option, you can add to keywords:
(assoc-in node [:context :metabase/hydrate true]) 
which will appear in the analysis output
#2022-04-2819:18snoeIf I hook hydrate and grab the keyword node, would I be able to look up the context added from other analysis? That would be pretty powerful for hooks. Not sure if it'll work in this case as the registry is determined at runtime, so the call site might be analyzed before the defn.#2022-04-2819:20borkdudeThat's not how it works. The keyword + context ends up as is in the analysis. It doesn't mean that all other identical keywords get that context added, it's just a way to add extra info to the analysis output#2022-04-2819:30snoeOk, thats what I suspected, but if it did work that way would it could be pretty powerful; I think I could probably use it to solve this :) handwaving It would probably require a type of post-analysis hook that could only register findings/keyword/var/var-usage but have access to :context values for a given keyword/symbol.#2022-04-2818:11borkdudebut if you would use namespaced keywords throughout, you would be able to find keyword references unambiguously - or maybe stepping away from keyword indirections is an even better solution#2022-04-2819:08snoeaye, was curious how far I can get without code changes, but that's my intuition at all.#2022-04-2819:31snoeThanks for the thoughts, appreciated!#2022-04-2913:33Braden Shepherdsonhere's a weird one: this is tickling :redundant-do despite having two things in it at least in CLJ mode https://github.com/metabase/metabase/blob/master/shared/src/metabase/mbql/util.cljc#L672-L676#2022-04-2913:35borkdude@braden.shepherdson cljc files are linted twice, once for each language context#2022-04-2913:36Braden Shepherdsonsure, that makes sense. but I'd argue a do is only redundant if it's not needed in any language.#2022-04-2913:39borkdudeyou're technically correct, but that's not how it currently works#2022-04-2913:45borkdudeyou could just put :cljs nil there to get rid of the warning#2022-04-2913:48Braden Shepherdsonyeah, that works. thanks for the prompt reply.#2022-04-2917:10Noah Bogart(and some-var) throws a single-logical-operand warning (which I just realized is undocumented). How would you feel about a similar check for (-> some-var) and (->> some-var)?#2022-04-2917:28borkdudecould work. we could call it :redundant-call or something: a call which just returns its argument#2022-04-2918:48wilkerluciothis may be specific enough to be named :redundant-threading?#2022-04-2918:52borkdudeyes, we can call it that#2022-04-2919:12wilkerluciomaybe :redundant-thread is simpler#2022-04-2919:13borkdudeI suggested that, but it might be confusing since it could also mean (Thread. (fn []))#2022-04-2919:13wilkerluciohumm, makes sense#2022-04-2919:14wilkerlucioalthough, is that (Thread. (fn [])) ever to be considered a redundant thread?#2022-04-2919:14borkdudegood point. and people can just look up what it means of course#2022-04-2919:14wilkerluciooverloading of names, always fun 😛#2022-05-1502:44Noah Bogarthttps://github.com/clj-kondo/clj-kondo/pull/1692 here's my attempt at this lint#2022-04-3001:57ericdalloOn clojure-lsp we have a feedback progress bar both on Editors and CLI, we update the progress bar at each stage of clojure-lsp startup, and usually the part which takes more time is external analysis (when not cached) and project analysis. ATM we have a (not that) smart update for external deps, updating according to the batch calls to kondo (3 batches means 20/45/60 % for example) and for project analysis we hardcode update to 95%, I was wondering if we could have a kondo hook for each path analyzed so we can have more precise feedback at lsp side 🧵#2022-04-3001:57ericdalloFor example, if we know we are calling kondo for a project classpath with 80 filenames, I'd expect kondo to call a callback function 80 times for each file which we could then update the progress bar#2022-04-3001:58ericdallothe 2 call (project source code analysis) is a little bit tricky as we usually pass folders not specific filenames (`[ "src/" "test"` etc), so it'd be fantastic if kondo could expand and return the hooks for each file
#2022-04-3001:59ericdallodoes that makes sense for kondo?#2022-04-3002:13ericdalloI wonder how that would affect performance, probably not relevant#2022-04-3006:09borkdudeSure#2022-04-3015:54ericdallotks: https://github.com/clj-kondo/clj-kondo/issues/1675#2022-04-3011:00andrewzhurovwhat does hof stands for in https://github.com/clj-kondo/clj-kondo/blob/d012ab5614e0824dd51da9946dc8708dee7f498d/src/clj_kondo/impl/analyzer.clj#L1622?#2022-04-3011:02borkdudehigher order function#2022-05-0220:44FABRICIOHello everyone 🙂 i'm experiencing one linter problem with the extension... it is not recognizing the simbols defined inside the reagent/with-let function, so it underline every repetition of those symbols in the function... i'm in a mac Monterey. I'm using latest versions for clj-kondo, calva and vscode as well Thanks in advance for any help you could give me! something like this:#2022-05-0220:45borkdude@fabriciocozzarolo configuration: {:lint-as {reagent.core/with-let clojure.core/let}}#2022-05-0220:49borkdudePerhaps this configuration could be automatically exported by reagent - is there anyone who is maintaining it, in this channel?#2022-05-0220:56FABRICIOthat is already in the config file of the .clj-kondo folder in the project... is there another place where i should put it?#2022-05-0220:57borkdudeNo, that should be it. Can you post the config in a gist or so? I suspect there is something wrong there#2022-05-0221:00FABRICIO
{:lint-as {reagent.core/with-let    clojure.core/let
           devcards.core/defcard-rg clojure.test/deftest}
 :linters
 {:unused-namespace {:level :error
                     :exclude [day8.re-frame.async-flow-fx]}
  :unresolved-var {:exclude [honeysql.helpers
                             honeysql-postgres.helpers
                             honeysql.core]}
  :consistent-alias
  {:level   :error
   :aliases {backend.app.controller-behaviors.login login-behaviour
             backend.app.models.common              mc
             backend.app.views.common               views
             clojure.string                         str
             framework.components.session.backend   session-backend
             frontend.components.actions-panel      action-panels
             frontend.components.autocomplete       auto
             frontend.components.buttons            buttons
             frontend.components.icons              icons
             frontend.components.toggles            toggles
             frontend.routing.core                  routing
             honeysql.core                          sql
             honeysql.helpers                       sqlh
             malli.core                             m
             malli.error                            me
             malli.util                             mu
             re-frame.core                          rf
             reagent.core                           r
             reagent.dom                            rdom}}}}
#2022-05-0221:02borkdudeThat looks good. What does the namespace form in your code look like?#2022-05-0221:03FABRICIO
(ns frontend.pages.assignments.components.positions.view
  (:require
    ["@heroicons/react/solid" :as heroicons]
    ["react-select" :as rs]
    ["react-select/creatable" :as rsc]
    [clojure.string :as str]
    [frontend.components.candidate-name-link :as cn]
    [frontend.components.dropdown-menu :as dropdown-menu]
    [frontend.components.expander-collapser :as ec]
    [frontend.components.expertise :as exp-icon]
    [frontend.components.icons :as icons]
    [frontend.events.delete-modals :as delete-modal-events]
    [frontend.events.positions :as positions-events]
    [frontend.events.team-assignments :as assignment-events]
    [frontend.events.teams :as teams-events]
    [frontend.pages.assignments.components.note :as note]
    [frontend.pages.assignments.components.positions.events :as events]
    [frontend.pages.assignments.components.positions.subs :as subs]
    [frontend.pages.assignments.defines :as defines]
    [frontend.pages.assignments.subs :as assignment-view-subs]
    [frontend.subs.expertises :as expertises-subs]
    [frontend.subs.positions :as positions-subs]
    [frontend.subs.team-assignments :as assignments-subs]
    [malli.core :as m]
    [malli.error :as me]
    [malli.util :as mu]
    [re-frame.core :as rf]
    [reagent.core :as r]
    [shared.specs.frankie-domain :as fd]
    [shared.time :as time]))
#2022-05-0221:04FABRICIOi tried to disable kondo and let calva use it but it didin't work either#2022-05-0221:04borkdudeThis also looks good. Can you make a reproduction repo?#2022-05-0221:05FABRICIOdo you mean to create github repo and share the project as it is?#2022-05-0221:06borkdudeThen I can clone it and try it locally tomorrow. Well, not as is, unless it's already open source, but some project which demonstrates the same error#2022-05-0221:07borkdudeAlso try linting on the command line and see if that also exhibits the error#2022-05-0221:07borkdudewith the clj-kondo binary.#2022-05-0221:07FABRICIOyeah because i dont know if i can share it.... i will try to reproduce in another one and let you know... thank you very much 🙂#2022-05-0221:21FABRICIO
~/Desktop/clojure/Frankie/src/frontend/pages/assignments/components> clj-kondo --lint positions
positions/events.cljs:1:5: error: Namespace name does not match file name: frontend.pages.assignments.components.positions.events
positions/subs.cljs:1:5: error: Namespace name does not match file name: frontend.pages.assignments.components.positions.subs
positions/view.cljs:1:5: error: Namespace name does not match file name: frontend.pages.assignments.components.positions.view
linting took 339ms, errors: 3, warnings: 0
#2022-05-0221:21FABRICIOi get this when i try to lint the folder containing the file#2022-05-0221:22borkdudeso, no errors about reagent, right?#2022-05-0221:23borkdudethen this probably has to do with how you open the project in Calva.#2022-05-0221:23borkdudemake sure you open the project in the root folder and the config directory is also in the root folder, in .clj-kondo/config.edn#2022-05-0221:23borkdudecc @U0ETXRFEW @UKFSJSM38#2022-05-0221:25ericdalloyeah, sounds like wrong project root, maybe check server logs may help: https://clojure-lsp.io/troubleshooting/#2022-05-0221:27FABRICIOwhat do you mean with how i open the project in calva?:thinking_face: .clj-kondo folder is in the root folder of the project.... nothing changed there since las 3 months#2022-05-0221:29ericdalloclojure-lsp used by calva uses the project root that vscode sets, which is the project opened root#2022-05-0221:38FABRICIOis there a special way of opening a project in vscode? y always add the project folder from the explorer to the workspace.... where can i see or modify that root folder you're saying vscode sets?#2022-05-0221:39ericdalloif you code my-project-root should be enough, just open your project root as a folder#2022-05-0221:39ericdalloyou can't change that AFAIK on vscode#2022-05-0221:40pezAdding the project folder to the workspace should work fine.#2022-05-0221:42pez@fabriciocozzarolo, if it works with opening the project root in a window, but not when adding the project folder to the workspace, then we have a bug in Calva, I think.#2022-05-0221:42ericdalloclojure-lsp logs would show which project root is set#2022-05-0221:43pezYes, the clojure-lsp button shows a menu from which you can show server info, @fabriciocozzarolo. See if the project root differs in the two scenarios.#2022-05-0221:54FABRICIOyep... it worked opening from the console... and the project-root-uri is different in the 2 windows... is there a way to change it or just drop the workspace and open a new one?#2022-05-0222:29pezIn what way are the Uri's different?#2022-05-0222:31pezPlease file an issue about this, describing the project setup and your workspace setup.#2022-05-0222:36FABRICIOthe uri was for another project in the workspace i had#2022-05-0222:37FABRICIOi tried removing that project and a calva error appeared, i clicked on the output log but it took me nowhere#2022-05-0222:48FABRICIOand the lisp serve felt down#2022-05-0222:56pezDon’t you get a menu for selecting which of the projects? What version of Calva is this?#2022-05-0223:03FABRICIOmm no... when is calva supposed to show a menu? i simply removed the project indicated in project-root-uri to see what happened and the lsp server turned off with the error#2022-05-0223:08FABRICIOi found that when i change the folders order in the workspace the project-root-uri key changes to the project i moved to the top in the explorer and automatically restart the lsp server#2022-05-0223:09FABRICIOand when i move this "Frankie" project (my main project) to the top of the explorer all the linter errors disappear....#2022-05-0223:11FABRICIOthat behavior wasn't like that before, because i always had at the top a folder with annotations that i use always in all the workspaces i have#2022-05-0305:18pezYes, these things have changed in Calva. Now we explicitly tell clojure-lsp where the project root is, where before it was often undefined for some cases. However, when there are multiple folders, we need a way to determine project root. With the REPL we ask the user. The issue here I think is that for clojure-lsp, we just pick the first workspace folder.#2022-05-0305:19pezI note that the VS Code window is reloaded when project folders are reordered.#2022-05-0305:25pezAnyway, I think we can only ask clojure-lsp to analyse one project root. In the case of multiple workspace folders that means we should probably ask the user for the project root, like we do for the REPL connection.#2022-05-0305:26pezI wonder how other clients/servers solve this...#2022-05-0305:41pezI created an issue to track this. https://github.com/BetterThanTomorrow/calva/issues/1706#2022-05-0316:23FABRICIOthanks for your time guys!#2022-05-0317:42marciolHey friends, I'm trying to discover why my ignore hints aren't working, but don't know even how to start debugging the issue. I'm using the "2022.02.09" version of clj-kondo.#2022-05-0317:44marciolIt's very strange because the :config-in-ns works.#2022-05-0317:46borkdudeconfig-in-ns is only available in the last version, so it's very strange that that would work, unless you're using clj-kondo via a downstream tool like clojure-lsp#2022-05-0317:46marciolYes, via clojure-lsp#2022-05-0317:47marciolI tested other hints, just the :private-call isn't working#2022-05-0317:47marciolAll others do#2022-05-0317:47borkdudecould be a bug#2022-05-0317:48marciolYes, I'll get the version of clojure-lsp I'm using, maybe the bug was already fixed by the way. Thanks @borkdude#2022-05-0317:50borkdude
$ clj-kondo --lint - <<< '#_:clj-kondo/ignore (defn- foo [])'
linting took 13ms, errors: 0, warnings: 0
#2022-05-0317:53marciol
~/Projects/Work/my-app (container-info *) $ lein lint
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Retrieving clj-kondo/clj-kondo/2022.04.25/clj-kondo-2022.04.25.pom from clojars
Retrieving org/babashka/sci/0.3.2/sci-0.3.2.pom from clojars
Retrieving org/ow2/asm/asm/9.2/asm-9.2.pom from central
Retrieving org/ow2/ow2/1.5/ow2-1.5.pom from central
Retrieving org/ow2/asm/asm/9.2/asm-9.2.jar from central
Retrieving org/babashka/sci/0.3.2/sci-0.3.2.jar from clojars
Retrieving clj-kondo/clj-kondo/2022.04.25/clj-kondo-2022.04.25.jar from clojars
test/com/my_app/my_ns/some_test.clj:79:1: error: #'my-app.my-ns/get-something is private
linting took 140ms, errors: 2, warnings: 0
#2022-05-0317:54marciolit's weird because I have all those hints on source#2022-05-0317:54borkdudeoh private-call, I mixed this up with unused-private-var :)#2022-05-0317:55borkdude@marciol I recommend using (#'my-ns/private-var 1 2 3) instead, then clj-kondo will not warn#2022-05-0317:55borkdudethat's how you'd do it in JVM Clojure as well#2022-05-0317:56marciolhmmm, nice. I'm trying to use it with circle-ci bond with-stub!#2022-05-0317:57borkdudeoh, that's a macro right? you could try :lint-as {circleci.bond/with-stub! clojure.core/binding]#2022-05-0317:57marciolhmmm#2022-05-0317:57borkdudeas you can use private vars as bindings in JVM Clojure as well without warnings and clj-kondo respects this#2022-05-0317:57marciolyes, it's a macro#2022-05-0317:58marciolThank you @borkdude, it's all I need gratitude-thank-you#2022-05-0318:28rayatHi, it looks like every use of & for rest/spread (not sure what it's technically called) is linted as an unresolved symbol? I don't think we've had any changes to our config recently that I'm aware would affect this. Any smells to follow? Any workarounds for the meantime? Example lint error:
Unresolved symbol: &
#2022-05-0318:34borkdudeRepro please. A screenshot and example lint error is not a repro we can do much with. Are you able to make an example file we can lint locally?#2022-05-0319:23rayatAh, your answer indicates this is not a known, or common user error, or some such thing, which is mostly what I had hoped for. I'll try to figure it out myself for now, and will reach out with repro if it persists. Thanks for responding so quickly and being down to help troubleshoot as usual!!!#2022-05-0319:34borkdudeIndeed, it doesn't ring a bell and should not happen with normal Clojure code#2022-05-0915:54rayatIn case you were curious, strangely, this is the result of something within the intersection of Calva, c-lsp, kondo and whatever peculiarities of our codebase working correctly now when it hadn't before. The & error was in fact not an false positive for rest/spread like kwarg args passing, but actually the usage of the special & "operator" within lilactown/helix. I ended up writing a couple hooks for helix to get everything working as expected. Thanks for everything again!#2022-05-0915:56borkdudecool! Maybe you can contribute the hooks to helix for everybody to enjoy?#2022-05-0915:58rayathttps://github.com/lilactown/helix/pull/93#2022-05-0915:58borkdudefantastic, good work @U037TPXKBGS!#2022-05-0916:04rayat3 questions about hooks if you don't mind: 1. what's the diff between your hooks.md doc doesn't differentiate I think 2. looking thru the rewrite-clj docs and noticing all the talk of the zipper API, it does look nifty. Would the kondo use-case make sense for providing the zipper API? Or have I maybe misinterpreted its intended use case? 3. I wanted to also catch and provide error diagnostics for cases of, for example, passing maps as children to be rendered in helix components. I can do that most trivially by checking if there's a map-node as a child somewhere, but that doesn't work if the map was bound to a symbol/var elsewhere and then the latter is instead passed, making it a token-node. Is there anything I can do within a linting hook to maybe "resolve" references "1 or 2 #2022-05-0916:04borkdude1. simply throwing doesn't allow you to configure the linter name and level#2022-05-0916:05rayatgosh you're responsive#2022-05-0916:05borkdude2. the zipper API was exposed in the past, but I ended up removing it because I didn't find it very useful for hooks, but might add it back if people want it#2022-05-0916:06borkdude3. not yet#2022-05-0916:08rayatDo you mind if I submit a PR for adding some of this stuff/my learnings to the hooks docs?#2022-05-0916:11borkdudePlease do! 🙏#2022-05-0917:41rayat@borkdude would love help knowing how we can enable similar linting for the generated symbols in https://github.com/lilactown/helix/blob/master/src/helix/dom.cljc. That is, users typically import/require syms from that ns and use em like (d/div {:some 'props} "some children"). It has similar linting rules as $ , but I don't know how to tell kondo to lint every sym as such. Any ideas?#2022-05-0918:17borkdude@U04V5V0V4 you could do this using :lint-as {helix.dom/a helix.foo.$}#2022-05-0918:17borkdudeyou'd have to repeat it for every tag in the config#2022-05-0918:52rayatAh, and could I do that as part of a helix PR, such that when consumers update to whatever helix version includes the new hooks/lint configs, they don't have to copy over every dom/* :list-as? Also dragging in @U4YGF4NGM for his take > btw I think you've tagged the wrong fellow#2022-05-0918:52borkdudeyes#2022-05-0920:46rayatWould you be open to a special lint-as* type key in config.edn that would accept something like:
:lint-as* { helix.dom/* helix.core/$ }
tbf I cannot think of another use-case beyond this specific one, but if there'd been interest in the past by other, I'll cast a small vote into that pool 😛
#2022-05-0920:47borkdudeI've solved this for namespaces like this: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#namespace-groups So you can define a group using a regex and then use the group name in the config. We could do the same thing for vars#2022-05-0920:50rayatOh cool, yeah that looks promising! It's not the biggest personal priority, and I'll see how @U4YGF4NGM feels about the upcoming big-ol-list of :lint-as that I'm opening, but if there's a way I can help out in your suggestion, lmk!#2022-05-0920:50borkdudeSo something like:
{:var-groups [{:regex ".*" :name all}]}
{:lint-as {helix.dom/all helix.core/$}}
#2022-05-0920:51rayatYep. Any clue what an exclusion override might look like with that? Eg in this helix case, almost all exported syms are applicable to $-like linting, except one or two of em.#2022-05-0920:52borkdudeI think you would have to take care of that in the regex#2022-05-0920:53rayatsure, fair enough#2022-05-0920:54borkdudeMaybe it should look like:
{:var-groups [{:regex "helix.dom/.*" :name helix.dom/all}]}
#2022-05-0920:54borkdudenot sure#2022-05-0920:54borkdudedidn't think hard enough about this specific case yet#2022-05-0920:54borkdudeso it would probably take me some more time#2022-05-0920:54rayatAnother question, in this helix case again, there are some platform reader tag-based syms exported, eg
#?(:clj (defmacro some-macro ...))
Would this lint those?
#2022-05-0920:54borkdudeto properly do that#2022-05-0920:55borkdudeclj-kondo lints a .cljc file twice, once for :clj and once for :cljs#2022-05-0920:55rayatI think the latter more explicit/specific version might make more sense#2022-05-0920:55rayatAh right I recall now#2022-05-1318:05rayatHey @borkdude I'm sorry if this is dumb as usual etc. but couldn't discern much from the hooks docs. Also, I lack knowledge of the correct jargon, so forgive that as well: My hooks are overall working nicely, but inside fn calls that I've written the hooks for, symbols imported from other ns's like (nsname/some-fn ...) are linted as errors with Unresolved var: nsname/some-fn. Any pointers or smells as to what my hooks are doing wrong? Are those nsname/some-fn references treated as just raw symbols or something, and not as imported/namespaced ones? FWIW there are no lint errors for the same fns/symbols outside of my hook'd fns. Inside my hook, those sorts of things are expanded as (api/token-node whatever-the-symbol-is-verbatim). Should I be using a different approach to those nodes, or making use of ns-analysis somehow? Thanks!#2022-05-1318:09borkdude@U037TPXKBGS 👋 "dumb as usual" not at all! :) The hook expands into code and then clj-kondo takes over as if the user had written that code. Perhaps you could just try to make such a fully written out example, without hooks, and then see how that's working.#2022-05-1318:15rayathmm, I'm guessing you mean by throwing in a (prn (api/sexpr my-hook-return-val)) in my hooks and paste it in from cli?#2022-05-1318:16borkdudeno, I mean, write out an example that would normally be returned from the hook code#2022-05-1318:16borkdudejust normal code as how the user would write it#2022-05-1318:16borkdudethen I expect you would also see the unresolved var#2022-05-1318:16rayatWell, that's assuming my hook is written correctly, right? That it accurately outputs what I would have written by hand?#2022-05-1318:17rayatBut ok I'll try that#2022-05-1318:17rayatThanks#2022-05-1318:21rayatOkay... I didn't do anything, but a manual cli lint + couple of clojure lsp restarts later, and it's no longer false-positive-ing the symbol references... wtf lol#2022-05-1318:21rayatDIdn't change any config or anything, and already restarted lsp server tons of times in the past 30 minutes#2022-05-1318:21rayatWell, in any case, thanks again!!!#2022-05-1318:22borkdudeit could be that the other ns wasn't linted yet#2022-05-1318:22borkdudeor not refreshed#2022-05-1318:22borkdudeyou're welcome#2022-05-0318:50devnwhat’s the right way to get kondo to not complain about hiccup? i added a lint-as for hiccup.def/defelem and hiccup.def/defhtml, but i am still seeing unresolved symbols for things that were created with defhtml, and unresolved vars for things like hiccup.form/text-field#2022-05-0318:50borkdudeIt depends on the syntax of those things :)#2022-05-0318:50borkdudeexamples would be helpful#2022-05-0318:51devnexample meaning a link to the source of these things?#2022-05-0318:52devn
(defmacro defhtml
  "Define a function, but wrap its output in an implicit html macro."
  [name & fdecl]
  (let [[fhead fbody] (split-with #(not (or (list? %) (vector? %))) fdecl)
        wrap-html     (fn [[args & body]] `(~args (html 
#2022-05-0318:52devn
(defmacro defelem
  "Defines a function that will return a element vector. If the first argument
  passed to the resulting function is a map, it merges it with the attribute
  map of the returned element value."
  [name & fdecl]
  `(do (defn ~name 
#2022-05-0318:52devn
(defelem text-field
  "Creates a new text input field."
  ([name] (text-field name nil))
  ([name value] (input-field "text" name value)))
#2022-05-0318:52borkdudeI'm more interested in the usages of those things#2022-05-0318:52devnoh sure, sorry#2022-05-0318:53borkdudeas that is what matters for linting#2022-05-0318:53devn
(defn foo
  []
  (h.form/text-field {:class "hello"}))
gives me an unresolved var on h.form/text-field
#2022-05-0318:54borkdudeoh I see#2022-05-0318:54borkdudeyou should do lint-as defelem clojure.core/defn and then re-lint your dependency#2022-05-0318:55borkdudeif you are using clojure-lsp, that means lsp-workspace-restart#2022-05-0318:55devndefelem without it’s namespace?#2022-05-0318:55borkdudeno, with, I was just lazy in typing#2022-05-0318:55devni did a restart workspace, and have
{:list-as {hiccup.def/defelem clojure.core/defn
           hiccup.def/defhtml clojure.core/defn}}
#2022-05-0318:55devnlet me do it one more time with feeling just to be sure#2022-05-0318:57devngoing to restart my emacs and manually delete the .cache dir#2022-05-0318:58borkdudedefine, "the cache dir"#2022-05-0318:58devn.clj-kondo/.cache#2022-05-0318:58borkdudesounds good#2022-05-0319:01devnclears all of them up except for:
(h.def/defhtml bar
  [& content]
  [:body content])
#2022-05-0319:01devnwhere bar and content are unresolved symbols#2022-05-0319:03borkduderight#2022-05-0319:04borkdudethat's weird btw, I would expect that syntax to be equivalent to core defn#2022-05-0319:04borkdudewhat does your lint as look like?#2022-05-0319:05devnwhat i posted above, both being treated as clojure.core/defn — for kicks i tried to use the def-catch-all for defhtml, but same thing#2022-05-0319:06borkdudecan you post your exact config please?#2022-05-0319:06borkdudeoh I see#2022-05-0319:06devnomg#2022-05-0319:06borkdudesorry, I'm doing 10 things at once#2022-05-0319:06borkdudeI can take a look at this tomorrow#2022-05-0319:06devnconfig posted above was :list-as, not :lint-as facepalm#2022-05-0319:07borkdudehehe ok then#2022-05-0319:07devnsorry for the bother!#2022-05-0319:07borkdudeno problem#2022-05-1318:05rayatHey @borkdude I'm sorry if this is dumb as usual etc. but couldn't discern much from the hooks docs. Also, I lack knowledge of the correct jargon, so forgive that as well: My hooks are overall working nicely, but inside fn calls that I've written the hooks for, symbols imported from other ns's like (nsname/some-fn ...) are linted as errors with Unresolved var: nsname/some-fn. Any pointers or smells as to what my hooks are doing wrong? Are those nsname/some-fn references treated as just raw symbols or something, and not as imported/namespaced ones? FWIW there are no lint errors for the same fns/symbols outside of my hook'd fns. Inside my hook, those sorts of things are expanded as (api/token-node whatever-the-symbol-is-verbatim). Should I be using a different approach to those nodes, or making use of ns-analysis somehow? Thanks!#2022-05-0410:09Anders EknertHey! 🙂 When running clj-kondo via the lein plugin, it reports calls to abs as unresolved.. I guess it’s depending on an older version of Clojure than 1.11? Can I force it to use the Clojure version defined in my project, or should I open a ticket in the lein-clj-kondo repo?#2022-05-0410:20borkdude@anders982 If you lint the clojure version that is used within your project, this should resolve itself#2022-05-0410:21borkdudeI don't see any such warning with the latest clj-kondo:
$ clj-kondo --lint - <<< 'abs'
linting took 140ms, errors: 0, warnings: 0
#2022-05-0410:22Anders EknertRight - this only pertains to the lein plugin - not when running clj-kondo as standalone#2022-05-0410:23Anders EknertBut the lein plugin should work as well, no? 🙂#2022-05-0410:25borkdudeI don't see why the lein plugin should have a different clj-kondo version.#2022-05-0410:27Anders EknertI’d guess it’s from here https://github.com/clj-kondo/lein-clj-kondo/blob/master/project.clj#L8#2022-05-0410:29borkdudewell, you can bump the version yourself in your project.clj?#2022-05-0410:36Anders EknertHow would I do that? Just adding the dependency to the project does not seem to affect what’s being used by the :plugins . Sorry for the noob questions.. this is all kinda new to me 😬😅#2022-05-0410:40borkdudeI'm not sure either :) maybe @UKFSJSM38 knows #2022-05-0411:51ericdalloHum, maybe lein-clj-kondo is using a old clojure from it's deps ?#2022-05-0411:52ericdalloOh, not really, it's using a way older clj-kondo https://github.com/clj-kondo/lein-clj-kondo/blob/master/project.clj#L8#2022-05-0411:53ericdalloWe should bump it to latest kondo and release a new plugin version#2022-05-0411:53Anders Eknertsounds good! 😃#2022-05-0412:10borkdudewell, you have full permission on that repo @UKFSJSM38, go ahead :)#2022-05-0412:10Anders EknertThanks @UKFSJSM38 :thumbsup: And @U04V15CAJ 🙂#2022-05-0412:23ericdallosure, will do! Meanwhile @anders982 I suggest you take a look at https://github.com/clojure-lsp/lein-clojure-lsp, which has clj-kondo diagnostics and more features like clean-ns and format#2022-05-0412:26Anders Eknertinteresting! will do, thanks :thumbsup:#2022-05-0412:50Anders Eknertjust tried that plugin, but seeing:
$ lein clojure-lsp clean-ns --dry
clojure.lang.Compiler$CompilerException: Syntax error compiling deftype* at (rewrite_clj/node/stringz.cljc:16:1).
#:clojure.error{:phase :compile-syntax-check, :line 16, :column 1, :source "rewrite_clj/node/stringz.cljc", :symbol deftype*}
followed by a very long trace.. some known issue?
#2022-05-0412:50ericdallono, probably a conflict with rewrite-clj, any other plugin that uses rewrite-clj? like that old clj-kondo?#2022-05-0412:51borkdudeGoing back to the original problem though, I think users should have a way to bump clj-kondo without changing that plugin#2022-05-0412:51borkdudeI would be surprised if lein didn't support that in profiles.clj or so#2022-05-0412:51ericdalloI'm not aware of that feature @U04V15CAJ if we find it, I'd like to use on lein-clojure-lsp as well 😂#2022-05-0412:52borkdudeMaybe try #leiningen?#2022-05-0412:53Anders Eknert@UKFSJSM38 you were right - removing the lein-kibit plugin “fixes” the issue#2022-05-0412:55borkdudeclj-kondo does not use rewrite-clj directly, it has a forked version inside of it#2022-05-0412:55borkdudethe problem such as above usually comes from libraries that are AOT-ed right? I hope clojure-lsp doesn't do that#2022-05-0412:58ericdalloyeah, AFAIK we don't do that, we just uber it on build.clj but not uber-aot https://github.com/clojure-lsp/clojure-lsp/blob/master/cli/build.clj#L114#2022-05-0412:58ericdalloUnless I'm doing something wrong there#2022-05-0412:59borkdudewhen deploying to clojars you should not make an uberjar#2022-05-0412:59ericdallooh, good point, I think this was because of a old refactor, we should not uber indeed!#2022-05-0412:59ericdalloI'll fix it soon and release a version without that, thanks!#2022-05-0413:03Anders Eknertwould that be related to my problem, or just a good fix regardless? 🙂#2022-05-0413:03borkdudecould be related#2022-05-0413:03Anders Eknert:thumbsup: I’ll keep a watch for updates then, thanks!#2022-05-0413:05ericdalloI can take a look on both things later today#2022-05-0413:05Anders EknertThanks Eric :thumbsup:#2022-05-0509:37Anders Eknert@UKFSJSM38 I saw the new update and tag (0.1.4) to lein-clj-kondo, but looks like the publishing step failed#2022-05-0510:50ericdalloYeah, I had some issues with the clojars token, I'll fix it soon#2022-05-0513:17ericdalloFixed, released lein-clj-kondo 0.1.4 @anders982#2022-05-0513:17Anders EknertAwesome, thanks! 😃#2022-05-0720:51Anders EknertFinally got some time to bump the dependency. The good news is that the new version solves the “unresolved” problem from earlier version. The bad news is that it seems to have brought in the same problem I previously reported with lein-clojure-lsp — it doesn’t work as long as lein-kibit is also a in the :plugins vector 😞 The stack trace looks different:
clojure.lang.Compiler$CompilerException: Syntax error compiling var at (edamame/impl/parser.cljc:100:1).
#:clojure.error{:phase :compile-syntax-check, :line 100, :column 1, :source "edamame/impl/parser.cljc", :symbol var}
...
Caused by: java.lang.RuntimeException: Unable to resolve var: edn/read-symbolic-value in this context
But except for that the problem (and the workaround) looks identical
#2022-05-0815:26ericdalloWe release lein-clj-kondo with lein deploy clojars , that should not create a uber, but a jar only, right @U04V15CAJ?#2022-05-0815:28borkdudeCorrect #2022-05-0816:51Anders Eknerthmm… could something else have changed between releases that would cause this? it’s literally the only change I make:
❯ lein clj-kondo --lint src
linting took 299ms, errors: 0, warnings: 0

# bumping :plugins lein-clj-kondo "0.1.3" -> lein-clj-kondo "0.1.4" 

❯ lein clj-kondo --lint src
clojure.lang.Compiler$CompilerException: Syntax error compiling var at (edamame/impl/parser.cljc:100:1).
#:clojure.error{:phase :compile-syntax-check, :line 100, :column 1, :source "edamame/impl/parser.cljc", :symbol var}
If I comment out the lein-kibit plugin dependency, things work as before, but I’d rather not have to
#2022-05-0816:53ericdalloAny clues @U04V15CAJ ?I don't know too why that happens#2022-05-0817:45borkdudeI don't know anything about lein plugins, sorry#2022-05-0817:46borkdudePerhaps switch to deps.edn to invoke clj-kondo#2022-05-0510:10grahamcarlyleI'm setting up a project's clj-kondo config which uses an library that has an exported clj-kondo config. The manual recommends that I use clj-kondo with --copy-configs etc. and then refer to these copied configs via the :config-paths setting in the project's config.edn. This all works fine but I'm a worried that the libraries exported config will change and so my copy will unwittingly get stale. Do I just have to live with this risk, hoping that any change in the library will result in my stale copied config results in a linting fail, or is there some mechanism I could use to keep my copied config in sync with the library's exported version?#2022-05-0510:12borkdude@grahamcarlyle you don't have to set :config-paths anymore, I should probably remove that. as long as there is a two-level directory like .clj-kondo/foo/bar/config.edn in there, it will be picked up automatically. To keep up to date:
clj-kondo --lint $(clojure -Spath) --copy-configs --dependencies --skip-lint
#2022-05-0510:12borkdudeand then check into source control whatever is copied to .clj-kondo/... except the .cache directory#2022-05-0510:17grahamcarlyle@borkdude thanks I will remove my :config-paths setting. So I have to manually keep the copied config up to date, its a shame that this can't be done automatically by clj-kondo (via some integration with deps or whatever)#2022-05-0510:18borkdudeI expect the config churn to not be so great and with --skip-lint this should happen sub-second#2022-05-0510:18borkdudeyou could hook it to some git commit hook or bb task#2022-05-0610:46borkdudeHello y'all! I made a small documentation tool based on clj-kondo output. Example: https://github.com/babashka/sci/blob/master/API.md Repo: https://github.com/borkdude/quickdoc#2022-05-0611:03orestisHi! I'm using transit-cljs for the first time in this codebase, and I'm getting this unexpected error from clj-kondo: • cognitect.transit/reader is called with 1 arg but expects 2 or 3cognitect.transit/read is called with 2 args but expects 1#2022-05-0611:04orestisWith the linted function being:
(defn get-transit-var [x]
  (let [json (gobj/get js/window x)
        reader (transit/reader :json)]
    (transit/read reader (js/JSON.stringify json))))
And the require being [cognitect.transit :as transit]
#2022-05-0611:05borkdude@orestis Are you using this in a .cljc file?#2022-05-0611:05orestis.cljs#2022-05-0618:57borkdude@orestis The issue might be that clj-kondo has an older version of transit in its built-in cache#2022-05-0618:57borkdudeif you lint your dependencies, that should take care of the problem#2022-05-0619:11orestisI'm starting with linting dependencies and clearing the cache, but perhaps I need to look into the classpath generated for that. #2022-05-0619:25borkdudeeither way, issue welcome on github with repro#2022-05-1306:18orestisNo worries, I was preparing the classpath without the cljs alias. There was a mismatch between what VSCode/Calva was linting and what I was linting from the command line.#2022-05-0611:06orestisBut in the classpath there is also the CLJ version of transit.#2022-05-0611:09orestisI'm using the latest version for everything (transit, kondo)#2022-05-0617:48cldwalkerHi y'all. I'm looking to disable clojure linting in a .cljc file since I'm only wanting to lint it for cljs and nbb. I tried #?(:clj {:clj-kondo/config ^:replace {:linters {}}}) per https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#disable-all-linters-but-one but that doesn't seem to work. Any advice?#2022-05-0617:49borkdude@cldwalker try on the project level:
{:cljc {:features [:cljs]}}
#2022-05-0617:52cldwalkerThat works great for all files but unfortunately I have other cljc files that do need clj linting enabled. I tried it at the namespace level but no dice. Would namespace groups support it?#2022-05-0617:52borkdudeThe reader conditional processing happens before clj-kondo sees the ns form, so no#2022-05-0617:53borkdudeMaybe you're able to get away with a .cljs extension?#2022-05-0617:55cldwalkerOk. Should ^:replace work for namespace level configs or is that more for commandline usage per the example? I was hoping to disable all linters at once. For now I have a workaround that I disable new clj linter keys as they come up#2022-05-0617:56borkdudeYou can disable it with :output {:exclude-files "regex"}}#2022-05-0617:56cldwalker> Maybe you're able to get away with a .cljs extension? Unfortunately I can't because because nbb and cljs have different require semantics for this example e.g.:
#?(:org.babashka/nbb ["mldoc$default" :refer [Mldoc]]
   :default ["mldoc" :refer [Mldoc]])
#2022-05-0617:58borkdude@cldwalker Is one target the browser and the other Node.js, or both Node.js?#2022-05-0617:59cldwalker@borkdude one targets node and the other browser and node#2022-05-0618:00borkdude@cldwalker in nbb you can cheat by doing: (def mldoc (js/require "mldoc")) probably but this probably doesn't work for the browser#2022-05-0618:02borkdude@cldwalker I solved this problem in a different project by moving these differences to one spot and then use the required libraries from there.
(ns deps (:require #?(:org.babashka/nbb ["mldoc$default" :refer [Mldoc]]
   :default ["mldoc" :refer [Mldoc]])))

(def Mldoc Mldoc)
#2022-05-0618:02borkdude
(ns whatever (:require [deps :refer [Mldoc]]))
(.fooBar Mldoc)
#2022-05-0618:03borkdudeYou could also consider target :esm for both Node.js and browser and have everything the same as nbb#2022-05-0618:03borkdudeAnyway :exclude-files should solve it#2022-05-0618:04cldwalkerThanks for the suggestions. Will try em out and see what works#2022-05-0618:47Joshua SuskaloThanks a lot for the quickdoc tool @borkdude! I've wanted a reasonable doc tool for a while that produces something readable for my projects that can't be read by cljdoc or that I don't want to publish. I'd been using codox before, but even that's a pain to set up for some projects. I think this'll be a great tool to add to my toolbox. 🙂#2022-05-0618:47borkdudeCool :)#2022-05-0718:47pedrorgirardiI want to analyze a project’s classpath but I would like the analysis to be as “lean” as possible - basically var definitions. I’m using this config map:#2022-05-0718:47pedrorgirardi
{:var-usages false :var-definitions {:shallow true} :arglists true :keywords false :java-class-definitions false}
#2022-05-0718:48pedrorgirardiIs this the right way to go or is there a way to be “leaner”? 🙂#2022-05-0718:48borkdudeThat's about as lean as it gets right now#2022-05-0718:50pedrorgirardiCool! It’s all right then. I just wanted to double-check I wasn’t missing something. 😄 Thanks! 🙏#2022-05-0819:35borkdudeFor people interested in using #quickdoc, I now made a channel: #quickdoc#2022-05-0921:43rayatPer the following PR, is there in fact a lightweight way to test linting contributions? https://github.com/lilactown/helix/pull/93#pullrequestreview-966414595#2022-05-0921:46borkdudelint the libraries' source code or tests#2022-05-0923:20rayatI think, in terms of providing confidence to maintainers during lint-related PRs, automated testing was probs the idea in mind. Might that involve consuming clj-kondo as a lib and calling it upon hooks, etc?#2022-05-1001:56borkdudeYes, linting the actually library and tests with 0 lint warnings would be the ultimate test, don't you think?#2022-05-1001:57borkdudeYou can use clj-kondo as a JVM test lib for this #2022-05-1020:12rayat> https://clojurians.slack.com/archives/CHY97NXE2/p1652147809862699?thread_ts=1652132817.173779&amp;cid=CHY97NXE2 Yes indeed, I had assumed for some reason you were suggesting just running it by hand via CLI, and didn't and still don't yet know what it means to use it as a JVM test lib, though this can be explored at @U4YGF4NGM’s discretion I suppose!#2022-05-1009:54borkdudeHmm, this: https://clojure.org/guides/repl/enhancing_your_repl_workflow#writing-repl-friendly-programs would maybe be a reason to disable :redundant-fn-wrapper by default. I've come across this situation a couple of times now. /cc @ghadi: what do you think?#2022-05-1009:58imreWhat would be even more awesome is a linter that warns you about code being not repl-friendly, like #3 vs #4 at that link#2022-05-1009:59imreI kinda prefer #4 to #2 there so the wrapper is still redundant compared to using the var#2022-05-1010:00borkdudetrue#2022-05-1010:02imreI think your caution regarding the linter is right however. I would surely refactor from 2 to 3 by default as I don't have this thing on my mind most of the time.#2022-05-1017:29seancorfieldI just recently learned that #' is "dangerous" in cljs and it's much safer to use a wrapper function (via Thomas Heller).#2022-05-1017:30seancorfield(but I much prefer #' as the REPL-friendly approach in clj -- sounds like something I'll have to remember if I ever get back to writing cljs!)#2022-05-1017:31borkdude@U04V70XH6 if you're writing #joyride scripts, #' works just fine since vars are more like Clojure JVM in SCI, even in JS :)#2022-05-1017:37seancorfieldAh, good to know. Thank you!#2022-05-1118:37Noah Bogarti've been writing a lot of hooks for my company's codebase and they've been great. i'm interested in writing something that checks multiple nodes at once. is that possible? are there any plans for such a thing?#2022-05-1118:56borkdudeMore details? I don't know what you mean with multiple nodes at once :)#2022-05-1118:58Noah BogartFor example, I'd like to be able to write a hook that operates on a whole file, to allow for writing versions of :redefined-var.#2022-05-1118:59borkdudeah multiple top level nodes...#2022-05-1118:59Noah Bogarthttps://clojurians.slack.com/archives/C053AK3F9/p1652285637355079 gave me inspiration but there are multiple uses that come to mind#2022-05-1119:00borkdudefor warn on reflection I already have an issue: if you do Java interop and that form isn't there, then warn#2022-05-1119:00Noah Bogarti could write that in something other than clojure or just not using clj-kondo, lol, but it's so dang handy#2022-05-1119:01borkdudefor re-defined var, this is already a linter, what would you like to do differently there?#2022-05-1119:02borkdudeI see no reason why we couldn't have such a hook, but trying to get more compelling reasons for it#2022-05-1119:06Noah BogartAt my job, we have separate namespaces for groups of routes using compojure.core/defroutes. We tend to keep those at the bottom of each of their files, but sometimes extra functions or comment blocks or other things can end up below. I'd like to enforce that each defroute expression is the final expression in a given namespace#2022-05-1119:07borkdudeanother compelling thing could be to lint your own .edn files#2022-05-1119:07borkdudeso the hook could be named :analyze-file I guess?#2022-05-1119:07borkdudewhich is called at the beginning of any file#2022-05-1119:07borkdudeand the result can be transformed which will then be linted#2022-05-1119:07Noah Bogartin addition to the one about requiring (set! *warn-on-reflection* true) below each ns form#2022-05-1119:08Noah Bogartyeah, that's a good way to do it, actually#2022-05-1119:09borkdudeso there is one question that comes up with .cljc files. clj-kondo transforms such a file once for :clj and once for :cljs and then lints it#2022-05-1119:09borkdudeI suspect this hook wants to see the already transformed file... right?#2022-05-1119:09borkdudeelse the user gets to deal with the difficulties of reader conditional processing#2022-05-1119:12Noah Bogartthat would probably be good. then users can write (defn my-file-hook [{:keys [lang]}] (when (= :clj lang) ...))#2022-05-1119:14borkduderight#2022-05-1119:14borkdudeCan you write all of the above up in an issue?#2022-05-1119:14Noah Bogartyes! i'll write it up for you#2022-05-1119:33Noah Bogarthere you go! https://github.com/clj-kondo/clj-kondo/issues/1690#2022-05-1119:38Noah Bogartthanks so much for being open to this idea! glad I could work through it with you#2022-05-1119:39borkdudeThis touches on some a thing (linting .edn files) that was already in the queue for a while and I like this solution better since it's more flexible#2022-05-1119:33Noah Bogarthere you go! https://github.com/clj-kondo/clj-kondo/issues/1690#2022-05-1214:45pinkfrog@seancorfield I saw your dot-clojure uses eastwood. I just checked the docs of eastwood, seems most functionalities are covered by clj-kondo. Would like to know your use case on it.#2022-05-1214:58seancorfieldHistorical, really. HoneySQL has Eastwood as part of its CI pipeline. I use clj-kondo "live" in my editor for stuff but haven't taken the time to figure out how to tune it for use in CI, whereas Eastwood is pretty easy for that -- although I only use Eastwood on that one project (and probably wouldn't use it if it weren't already setup when I inherited HoneySQL).#2022-05-1306:26pinkfrogYes it possible to disable warning on “RELEAZE” version (e.g., https://github.com/clj-kondo/clj-kondo/blob/919478cdfc58b47dd48a7383c9b3a6de2b507b1f/test/clj_kondo/deps_edn_test.clj#L106).. I didn’t find the relevant settings in the default config: https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/config.clj#L6#2022-05-1306:29borkdudeCan you try to put #_:clj-kondo/ignore in front of it?#2022-05-1306:31pinkfrogI’d like to control it in ~/.config/clojure/clj-kond/config.edn
#2022-05-1306:36seancorfieldThe only place I would use "RELEASE" is in my dot-clojure file for dev tooling -- which clj-kondo isn't going to be checking generally (except when you're editing it -- but not when you're working on actual projects). Actual projects should never use RELEASE. As of Maven 3.5.2 it's deprecated and will likely stop being supported at some point.#2022-05-1306:36seancorfieldIt breaks dependency caching in the CLI as well, another reason to avoid it.#2022-05-1307:03borkdudeAnd for the sporadic usage, you can use:
{:deps {foo/bar #_:clj-kondo/ignore {:mvn/version "RELEASE"}}}
#2022-05-1314:09pinkfrog> It breaks dependency caching in the CLI as well, another reason to avoid it. I haven’t tested it (and not sure how it is tested). But on the slightest possibility, will “RELEASE” make the path calculation slow, is this what breaks dependency caching in the CLI as well means?#2022-05-1314:17borkdudeIt doesn't make it slow, as the text is just hashed and that is the cache key. But you won't ever get the newest RELEASE version unless you have a cache miss.#2022-05-1314:22pinkfrogAh. That defeats the purpose of release (to keep it updated)#2022-05-1314:25borkdudeYes, unless you want to use -Sforce all the time#2022-05-1314:25borkdudeI made a command line tool which can quickly update a certain dependency to the newest, if that's interesting to you: https://github.com/babashka/neil It runs in milliseconds with babashka. There is also the excellent antq tool to update dependencies.#2022-05-1314:38pinkfrogThanks. I mainly use > There is also the excellent antq tool to update dependencies.#2022-05-1315:17seancorfieldantq is awesome. We have a daily cron job to provide us a nice report each day of outdated deps in our monorepo. Mostly, we do patch updates as a matter of course every build cycle and often any minor updates too, at least with Clojure libs which are typically really good with backward compatibility... Java libs, not so much.#2022-05-1320:03Noah Bogartwould it be possible to expose the helper function arity-error in hooks? I discovered that when I use :analyze-call to rewrite a custom macro, clj-kondo stops checking arity on the call, so I wrote my own version of arity-error#2022-05-1320:05borkdudeJust calling reg-finding! with type :incorrect-arity does not work I guess? Do you have a github link to that function you want to get in?#2022-05-1320:06borkdudeWe could also try to maintain the arity errors as seen pre-transformation#2022-05-1320:06borkdudeThat would maybe be a better thing to do#2022-05-1320:10Noah BogartI did not know that you could exclude the :msg in reg-finding! so that explains it lol#2022-05-1320:18Noah Bogartactually, I made a mistake so that's not working as I thought. I can private message you the macro and the hook, if you want#2022-05-1320:18borkdudeI think reg-finding expects :message#2022-05-1320:56Noah Bogartif i use :incorrect-arity but don't provide a :message, then the error just says error: with no message#2022-05-1320:56borkdude🤷#2022-05-1320:57Noah Bogartyeah, this isn't mean to be a bug report, just that if it's easier to expose arity-error, i would use it lol#2022-05-1614:07pinkfrogFor
:unused-private-var 
  {:exclude [user]}}
cljkondo errs with:
Expected fully qualified symbol, got: user {:type :clj-kondo/config}
#2022-05-1614:08borkdudeyes, you need to specify the fully qualified symbol of the var#2022-05-1614:11pinkfrogfor the user namespace, what’s the qualfied version?#2022-05-1614:13borkdudeThat is not how it works. It expects fully qualified var names there for which you want to suppress the usage warning.
(ns foo) 
(defn- foo [])
(ns bar (:require [foo]))
(foo/foo) ;; warning
:exclude [foo/foo]
#2022-05-1614:14pinkfrogPossible to exclude for all vars in a namespace?#2022-05-1614:14borkdudeNo#2022-05-1614:15pinkfrogSome use cases, the user.clj namespace, and also the public vars in bb task.clj files.#2022-05-1614:15borkdudeOh sorry, unused-private-var#2022-05-1614:15borkdudeI mixed it up with private-call facepalm#2022-05-1614:16borkdudeIf you want to suppress warnings inside of the namespace you can do two things:
(ns foo {:clj-kondo/config '{:linters {:unused-private-var {:level :off}}})
or:
:config-in-ns {user {:linters ...}}
#2022-05-1614:30pinkfrogIs it valid for unused-public-var.? Not working on my side
:config-in-ns
 {task.deps {:linters {:clojure-lsp/unused-public-var
                       {:level :off}}}}
#2022-05-1614:30pinkfrogWhere task.deps is the namespace in question.#2022-05-1614:32borkdudeoh I see, I thought you were asking about unused-private-var#2022-05-1614:32borkdudethis is a different linter#2022-05-1614:32borkdudewhich is implemented by clojure-lsp#2022-05-1614:32borkdudeI always turn this linter off to be honest ;)#2022-05-1614:33borkdudesince I already get the number of usages on my screen, I find the "unused" bit a bit redundant#2022-05-1614:34borkdudeYou can see the config for that one here: https://clojure-lsp.io/settings/#custom-clj-kondo-linters#2022-05-1614:36pinkfrogSo the config-in-ns only for internal linters?#2022-05-1614:36borkdudeIt works for clj-kondo's own linters, but I don't think clojure-lsp looks at that config#2022-05-1614:37borkdudeMaybe @UKFSJSM38 could fix that#2022-05-1614:37borkdudesince he was actually one of the people requesting :config-in-ns ;)#2022-05-1614:38pinkfrogI got it. It’s the linter that actively looks at the config file.#2022-05-1614:41borkdudein case of clj-kondo's own linters this is automatic, but for "external" linters they have to implement this themselves#2022-05-1614:45ericdalloOh, I think we need to fix on clojure-lsp to check config-in-ns indeed, will create a issue about that#2022-05-1614:46ericdallo@U04V15CAJ I think we would need to re-write lot of clj-kondo logic already has to check the ns and things like that, do you see any function we could expose on clj-kondo to make that easier for clojure-lsp?#2022-05-1614:48ericdallowell, I'll create the issue first on clojure-lsp#2022-05-1614:48borkdude@UKFSJSM38 For unused-public-var you'd only have to merge the config in :config-in-ns for the namespace the unused public var occurred in#2022-05-1614:48borkdudeclj-kondo already exposes a merge function, not sure what more it should expose#2022-05-1614:49ericdalloright, will check that merge function#2022-05-1614:49ericdallohttps://github.com/clojure-lsp/clojure-lsp/issues/981#2022-05-1716:07ericdallo@UGC0NEP4Y fixed, available on next release or via #clojure-lsp-builds#2022-05-1615:29plinsIm trying to use a lib that defines some functions dynamically using macros like
(defmacro log
  "Log an event and optional data structure at the supplied severity level
  using a logger that implements the Logger protocol."
  ([logger level event]      (log-form logger level event nil &form))
  ([logger level event data] (log-form logger level event data &form)))

(doseq [level '(report fatal error warn info debug)]
  (eval
   `(defmacro ~level
      ~(format "Log an event with %s logging level. See [[log]]." level)
      (~'[logger event]
       (log-form ~'logger ~(keyword level) ~'event nil ~'&form))
      (~'[logger event data]
       (log-form ~'logger ~(keyword level) ~'event ~'data ~'&form)))))
and of course clj-kondo is complaining.. is there a way of telling it on the config that these functions actually are defined?
#2022-05-1615:34imrehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2022-05-1615:35imreThat's what should be used for advanced macros like this#2022-05-1615:38plinsgiven that I know that this will generate fns named [report fatal error warn info debug] cant I “declare” them somehow on cfg file?#2022-05-1615:42borkdude@U3QUAHZJ6 You can even just write
(declare report fata error warn info debug)
in your clojure code and clj-kondo will get it :)
#2022-05-1615:43plinsthe thing is that this snippet lives in the lib namespace#2022-05-1616:54borkdudeyou can exclude warnings for all unresolved vars from namespace foo using:
{:linters {:unresolved-var {:exclude [foo]}}}
or exclude a selection of unresolved vars using qualified symbols:
{:linters {:unresolved-var {:exclude [foo/x]}}}
#2022-05-1616:54borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-var#2022-05-1617:20imreWhile that works, I was wondering if it would be possible to create a linter or some config that says "wherever this macro is called, these n symbols will be defined" (provide list of symbols)#2022-05-1617:22borkdudeYes, that is possible, using hooks, but those vars aren't created through a macro, but rather a global doseq#2022-05-1617:24imreOh true. Damn lisp curse#2022-05-1617:25borkdudeDamn eval ;)#2022-05-1619:48cldwalkerHas anyone tried linting with a cljs 1.11.X project? On a .cljs file with latest clj-kondo, I see update-keys and parse-long reported as unresolved symbols#2022-05-1619:49borkdude@cldwalker if you lint your cljs dependency then (in theory) it should work#2022-05-1619:52cldwalkerNot sure I understand the suggestion. The invocation I'm using is clj-kondo --lint /path/to/cljs/file . Should I be adding the cljs version as a dep?#2022-05-1619:55cldwalkerI tried the following as an alias but still get same error:
{:replace-deps {clj-kondo/clj-kondo {:mvn/version "2022.04.25"}
                                      org.clojure/clojurescript        {:mvn/version "1.11.54"}}
                       :main-opts  ["-m" "clj-kondo.main"]}
#2022-05-1620:07borkdudeWhat I mean is, you should lint your dependencies with:
clj-kondo --lint $(clojure -Spath) --dependencies --parallel
#2022-05-1620:07borkdudewith clojurescript on the classpath#2022-05-1620:07borkdudeso clj-kondo will actually analyze clojurescript and see those new functions#2022-05-1620:23cldwalkerAh. I guess my clj-kondo uses have been basic. I see I missed docs in https://github.com/clj-kondo/clj-kondo/blob/master/README.md#project-setup. Thanks for the help!#2022-05-1620:42borkdude@cldwalker Could you post an issue as a reminder to update the built-in cljs cache?#2022-05-1620:43cldwalkerSure#2022-05-1711:08chrisetheridgeis it possible to slurp a file inside a hook?#2022-05-1711:14borkdude@biscuitpants No, but it is possible to use require#2022-05-1711:17chrisetheridgethank you @borkdude! i'm trying to slurp an edn file when running a hook, but i think i can use analysis to work around this#2022-05-1711:27borkdudeI guess we could allow slurp, it doesn't seem to be a dangerous operation in clj-kondo hooks. The only problem is that it would be working-directory sensitive#2022-05-1711:28borkdudeand clj-kondo isn't always invoked from the same directory by different tools#2022-05-1711:30chrisetheridgegood point#2022-05-1711:30chrisetheridgei think i can work around the limitation though#2022-05-1711:32borkdudewhich limitation: slurp not being there, or the directory problem?#2022-05-1711:33chrisetheridgeslurp#2022-05-1711:33chrisetheridgethank you for the help#2022-05-1711:37imrethis sounds like something to support hugsql 🙂#2022-05-1711:38borkduderight#2022-05-1712:09lread@borkdude am I right in that https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#importing? I think I noticed we don't need to specify import configs in :config-paths anymore. Can do a little doc PR if the above is true.#2022-05-1712:10borkdudeyeah config-paths isn't necessary anymore when importing, if the library conforms the the suggested structure#2022-05-1712:11borkdudewe should also get rid of the printed suggestion after importing#2022-05-1714:59lreadCreated an issue for it: https://github.com/clj-kondo/clj-kondo/issues/1697#2022-05-1804:37Chris McCormickWhen I try to coerce a boolean to an int I get error: Expected: number or character, received: boolean. - is there a recommended way to treat true as 1 and false as 0? I'm using them for the Js .sort method.#2022-05-1805:21Noah Bogart(if X 1 0) is pretty simple#2022-05-1811:22roman01laHey 👋 Is it possible to analyze arbitrary calls, not only those specified via :hooks :analyze-call? What I'm trying is achieve is to build a linter rule that would find all defs for functions whose name has a certain prefix, then find usages of those function and check how they used. On that note, is it possible to inspect outer env of var usage? I think ideally I'd need access to entire ast, not sure if clj-kondo provides that?#2022-05-1811:24borkdudeHey @U0FR82FU1 - good to hear from you and to know you are OK!#2022-05-1811:24borkdudeTo your question, there is a recent open issue to get hold of the entire (raw!) AST here: https://github.com/clj-kondo/clj-kondo/issues/1690 It would not be so difficult to implement, but it still has to be done#2022-05-1811:25borkdudeOr would it also work if you could specify a regex for analyze-call?#2022-05-1811:25roman01laThanks! I'll add my use case to the issue.#2022-05-1811:27roman01la> Or would it also work if you could specify a regex for analyze-call? Hmm, that can work. But I also need access to outer AST of var usage
(defn f []
  (f2)) ;; usage of f2, lookup ast around it up to top level
#2022-05-1811:28borkdudeThe interesting bit here is to know that f2 is being used from f, right?#2022-05-1811:29roman01laYes, there are also more requirements. Let me put a comment in the issue, I'll describe everything I can think of#2022-05-1811:30borkdudeWe could additionally add more values to the input of the analyze-call hook, like the top level form of the call, which function it's used in#2022-05-1811:31borkdudeSo: specify a regex for analyze-call, and then receive: :top-level-node ... :etc ..#2022-05-1811:32borkdudeThis way you probably have to do less work yourself#2022-05-1811:52roman01laPosted https://github.com/clj-kondo/clj-kondo/issues/1690#issuecomment-1129913012#2022-05-1811:55borkdudeThanks! What I was thinking of also, is that you might like to use https://github.com/borkdude/grasp to run on the side#2022-05-1812:00roman01laI was honestly thinking to just run on a side cljs reader and inspect pure forms, that could be enough. But really it would be good to have a proper generic access to AST enriched with semantical constructs like: locals, globals, vars, functions etc#2022-05-1812:01borkdudeclj-kondo does not construct such an AST, it walks the raw rewrite-clj nodes and analyzes it as it goes#2022-05-1812:01borkdudeI think tools analyzer does construct such an ast#2022-05-1812:03roman01lahmm, I think a visitor pattern is fine, just that it's handy to have a reference to already analyzed AST#2022-05-1812:04borkdudeWith the analyze-file hook there won't be anything analyzed yet, you will just see the entire file as parsed with rewrite-clj. analyze-call is called "just in time" when the surrounding forms already have been analyzed and in that hook, we are able to provide some utilities for semantics, like "is this a local" or something#2022-05-1812:06borkdudealso clj-kondo internally has a notion of "callstack", a list of functions that were called before#2022-05-1812:07borkdudeif we could expose that in analyze-call, I think you would be able to lint things like: am I called in when or am I being called top-level#2022-05-1812:10borkdudelike, the callstack looks like this:
(when true (foo.bar/baz 1))
in analyze-call for foo.bar/baz:
:callstack ([foo.bar baz] [clojure.core when])
#2022-05-1812:11roman01lathat could be useful indeed#2022-05-1812:18borkdudeOK, perfect, so maybe we could start with that, or you can fork clj-kondo and check if that indeed would be useful and play with it#2022-05-1812:18borkdudethe callstack is a part of the ctx argument that floats around while visiting every node#2022-05-1812:48roman01la@U04V15CAJ do you want to create a separate ticket maybe where we can discuss what has to be done to enable specifically these rules? Would be good to track those ideas#2022-05-1812:51borkdudeYes, I think so#2022-05-1816:33borkdude@U0FR82FU1 I think I misunderstood. Could you please log the extra issues? I'm extremely busy the rest of the day and I'm going to forget#2022-05-1815:54dpsuttonIs it possible to emit #_ {:clj-kondo/ignore [:unused-public-var]} in hooks and macro expansions?#2022-05-1815:54dpsuttonfor macro, i’m trying
(defmacro defmodel [model-name & _args]
  `(do
     (def ~model-name "docstring" nil)
     (symbol "#_") {:clj-kondo/ignore [:unused-public-var]}
     (defrecord ~(symbol (str model-name "Instance")) [])))
but still getting the error
#2022-05-1816:12Joshua SuskaloSo macros can't output #_ comments because those comments happen at read time, not at compile or evaluation time#2022-05-1816:20Joshua SuskaloI believe you should be able to output them as a part of a hook using the rewrite-clj fork that's in sci, but I don't know if it would work.#2022-05-1816:21Joshua SuskaloI do want to note though that :unused-public-var is not a clj-kondo lint, it's a clojure-lsp lint and requires a namespace.#2022-05-1816:21borkdudeThis is not possible. Just emit one usage of the var to suppress the warning#2022-05-1816:21dpsuttonis it possible when using hooks?#2022-05-1816:21borkdudeNot possible right now#2022-05-1816:22Joshua Suskaloemitting a usage of the var in a hook is safe to do though because it doesn't affect the runtime use of the code#2022-05-1816:22Joshua Suskalono change to behavior, just suppresses the warning#2022-05-1817:20dpsuttonI’m trying to emit a usage in the hook but clojure-lsp is still saying it is unused#2022-05-1817:21dpsutton#2022-05-1817:22dpsuttonthe (hooks/list-node (list setting-name)) seems to be correctly marking the “getter” as used. But the version trying to call (setting-name! 3) to mark the setter as used is not fairing so well. The println is coming to the clojure lsp logs correctly:
(password-complexity! 3)
(session-cookies! 3)
(version! 3)
etc
#2022-05-1817:26Joshua Suskalooh that list node for the setter there isn't emitting a token node#2022-05-1817:26Joshua Suskaloit's emitting a symbol#2022-05-1817:27Joshua Suskalothe list node with the setting name is valid because it's coming from a token node that was read in before#2022-05-1817:27dpsuttoni’ve gone through lots of permutations. same thing with (hooks/token-node (symbol (str setting-name \!)))#2022-05-1817:28Joshua Suskaloright, I'd think you'd want (hooks/list-node (list (hooks/token-node (symbol (str setting-name \!))) (hooks/token-node 3)))#2022-05-1817:30Joshua SuskaloThe best way to print these by the way is to do a println on hooks/sexpr around the nodes, that way you can be sure that the whole structure is being built correctly#2022-05-1817:33dpsutton
2022-05-18T17:32:27.290Z  WARN [clojure-lsp.kondo:267] - Output from clj-kondo: (notification-retry-max-attempts! 3)
(notification-retry-initial-interval! 3)
(notification-retry-multiplier! 3)
(notification-retry-randomizaion-factor! 3)
(notification-retry-max-interval-millis! 3)
but still getting the unused error
#2022-05-1817:33dpsutton#2022-05-1817:33dpsutton
(doto (hooks/list-node
       (list
        (hooks/token-node (symbol (str setting-name \!)))
        (hooks/token-node 3)))
  ((comp println hooks/sexpr)))
#2022-05-1817:34Joshua Suskalohmm. Might be worth talking to @UKFSJSM38 about what this lint is doing then. Does it only track usages of public vars in other namespaces? I'm unsure since I always explicitly disable this lint because I develop libraries and public things won't be used more than half the time.#2022-05-1817:35Joshua Suskaloalso from that screenshot it seems like the setter isn't the issue. Not 100% sure, but the fact that the lint happens on the symbol right there tells me it's actually the getter that's having this lint, as the setter comes from a node which has no source location.#2022-05-1817:36Joshua Suskalo(unless you're explicitly adding that source location, unsure, I didn't read it that carefully)#2022-05-1817:36Joshua Suskalooh it looks like you are#2022-05-1817:36Joshua SuskaloCouldn't tell which one it was from the screenshot since the end of the var name is cut off#2022-05-1817:44borkdudeI will check back later, busy tonight#2022-05-1817:50ericdalloOne important point: the correct linter name is clojure-lsp/unused-public-var , so if using in a ignore it should be :clj-kondo/ignore [:clojure-lsp/unused-public-var]#2022-05-1817:51ericdallo> Does it only track usages of public vars in other namespaces? No, any usage/reference to that var would make clojure-lsp not return that lint#2022-05-1817:52Joshua SuskaloAlright, then something else weird is happening. I recommend @U11BV7MTK to do the hooks/sexpr trick to print the whole node that you're returning, rather than just a sub-portion of it and see what happens.#2022-05-1817:54ericdalloI thought borkdude said it's not supported, right?#2022-05-1817:54Joshua SuskaloYeah we moved to a different solution, emitting an actual usage of the var in the hook expansion#2022-05-1817:54Joshua Suskalowhich in theory would suppress the warning without needing that whole comment thing#2022-05-1913:26Nick McAvoyHi there. A quick suitability check, if you don't mind. The third argument to function foo in our codebase is either a string literal, or a variable which is a string literal, or a value out of a map literal. In other words, if you're reading the source, you can figure out the whole universe of strings passed for this argument; nothing is determined at runtime. Can clj-kondo be used to enumerate the set of strings passed to foo? At first glance, I see some information about arguments is available, but it doesn't seem like something of this sort would be.#2022-05-1913:43borkdudeHi @U01BA210C7K! Do you mean, implement a custom linter, or just have clj-kondo spit out some information separately from using it as a linter?#2022-05-1913:48Nick McAvoyThe latter - the information is valuable for a purpose different than linting.#2022-05-1913:49Nick McAvoyI started out looking into tools.analyzer, but wondered if that might be overkill#2022-05-1913:49borkdudeCan you give an example of a string coming from a variable or map?#2022-05-1913:49borkdudeBased on that I might have different options for you#2022-05-1913:51Nick McAvoy
(def bar "bar")

(foo arg1 arg2 bar)
(def foos {:baz "baz"})

(foo arg1 arg2 (:baz foos))
#2022-05-1913:55Nick McAvoyI'm afraid I must now turn in for the night - currently I'm in South Korea. I'll be back online tomorrow. Thanks so much for your quick response here, and for your help!#2022-05-1913:56borkdudeOK, come back tomorrow and then we'll talk more#2022-05-1913:56borkdudeJust ping me here#2022-05-1913:58borkdudeCurrently clj-kondo doesn't emit any literal values used as arguments, but I was thinking that grasp may help here: https://github.com/borkdude/grasp#2022-05-2007:50zakkorclj-kondo is giving me false positive warnings for unresolved vars in the superstring library - any idea how to fix?#2022-05-2007:51zakkorSomething is definitely funky because I can see the function signature and documentation on hover but it's still shown as unresolved#2022-05-2008:02borkdudeWhat does the function definition look like?#2022-05-2008:03zakkor
(defmacro ^:private alias-ns
  "Create an alias for all public vars in ns in this ns."
  [namespace]
  `(do 
#2022-05-2008:03zakkorso... that's probably why 😄#2022-05-2008:04borkdudeYou can exclude that namespace in the unresolved var linter perhaps #2022-05-2008:09zakkorThank you! That worked. For anyone else reading, I added:
:linters {:unresolved-var {:exclude [superstring.core]}}
to .clj-kondo/config.edn
#2022-05-2008:29borkdudeThere is a small library which can create stubs: https://github.com/clj-easy/stub And when you the lint that stub, you would get the right stuff#2022-05-2008:29borkdudeBut this is slightly more work than just excluding it#2022-05-2013:37raymcdermottwe all know that (myClass.) and (new myClass) are equivalent but did you know that full stops are becoming problematic?#2022-05-2013:37raymcdermotthttps://en.wikipedia.org/wiki/Full_stop#In_text_messages#2022-05-2013:38raymcdermottcould you make a clj-kondo warning against the use of (myClass.) form to protect Clojure users from such rudeness?#2022-05-2013:39raymcdermottThis is a Friday afternoon bit of fun. Please don't do it 🙂#2022-05-2013:41lreadThere was a period in my life I found offensive#2022-05-2013:42lreadAnd I think this linter should only be run periodically#2022-05-2013:43borkdudeNo.#2022-05-2013:43borkdudeDid I use full stop correctly?#2022-05-2013:43lreadYes#2022-05-2013:43borkdudeOK.#2022-05-2013:44lreadOooo... all caps... 😬#2022-05-2013:44raymcdermottnever stop.#2022-05-2013:45raymcdermott❄️ 🚨#2022-05-2014:59Joshua SuskaloExcuse me, the computer is my underling. I will use the exact amount of passive aggression that I want.#2022-05-2014:59Joshua SuskaloI'll have to disable this lint.#2022-05-2015:00borkdude#_:clj-kondo/ignore.#2022-05-2015:00Joshua SuskaloThanks.#2022-05-2307:49chrisetheridgeis it possible to modify the context passed to sci when running a hook? i.e this def https://github.com/clj-kondo/clj-kondo/blob/17c64ded054edf0b5fe87b26ac07d4043538285c/src/clj_kondo/impl/hooks.clj#L148#2022-05-2307:54borkdude@biscuitpants Currently not#2022-05-2307:55chrisetheridgeok cool. so i'd have to maintain a fork of Kondo if i wanted to do that (which i totally don't intend to do)#2022-05-2307:55borkdudeBefore talking about maintaining a fork, perhaps you could first explain what your use case / requirement is.#2022-05-2307:57chrisetheridgeits for supporting slurp in a hook, which i mentioned last week. just thinking of sane ways to support what i need to do, which is read a file to get information to use in linting#2022-05-2307:58borkdudeI then replied: we could support it, but the challenge is that clj-kondo isn't always called from the same working directory by different tools. And then you replied: it's ok, I found a different solution.#2022-05-2307:59chrisetheridgeyeah that solution requires running a script, which works ok for now. just thinking out loud really 😄#2022-05-2308:00borkdudewe could maybe call this function differently like: read-file-in-project or so which starts at the root of the project#2022-05-2308:00chrisetheridgethat would work nicely#2022-05-2308:02chrisetheridgei can work on a PR if you'd like @borkdude?#2022-05-2308:03borkdudeIn a call right now, but first read this please: https://github.com/clj-kondo/clj-kondo/blob/master/doc/dev.md#workflow#2022-05-2308:04chrisetheridgesure#2022-05-2309:08borkdude@biscuitpants Back from the call. So let's first write up an issue and think about alternatives, etc. I think this is important to do before writing any code, so we don't add things unnecessarily#2022-05-2309:10chrisetheridgemakes total sense and i agree 🙂#2022-05-2309:14borkdudeOK, issue welcome then :)#2022-05-2313:56grzmI have a single Java process that uses clj-kondo (via clj-kondo.core/run! ) to analyze different sub-projects in a monorepo (e.g., lib/a, lib/b, lib/c. It currently does so sequentially (first lib/a, then lib/b, then lib/c). To speed this up, I tried to run these in parallel (naïvely using pmap), but got lock contention on the clj-kondo cache. The job isn’t to refresh the respected clj-kondo caches: I’m writing out the clj-kondo results separately (along with some other data I’m collecting). Is this a case where I’d want to set :cache to false? Or perhaps set :cache-dir per-lib to isolate the caches? Or is there a better approach I’m not seeing?#2022-05-2313:59borkdude@grzm you could do :cache false, but this has the result that clj-kondo will not see connections between namespaces, e.g. it won't be able to say that you are calling a function with the incorrect amount of args#2022-05-2314:01borkdudeBut perhaps that's not important to your use case. If you can tell more about your use case, maybe I could give more appropriate advice#2022-05-2314:03borkdudeIt would surprise me if the cache lock contention was the reason that pmap wasn't much faster: clj-kondo doesn't spend a lot of time in reading/writing the cache#2022-05-2314:03borkdudeMaybe the overhead of pmap was just not worth it vs sequentially linting#2022-05-2314:04grzmI’m using the clj-kondo analysis to understand namespace and var dependencies between the subprojects. I’m essentially creating a big map {lib/a {:clj-kondo {,,,}}, lib/b {:clj-kondo {,,,}}#2022-05-2314:05grzmOh, it’s just stopping completely when it finds more than one thread is trying to read the cache file.#2022-05-2314:05borkdudehmm#2022-05-2314:06grzm(Apologies for not having the error at hand)#2022-05-2314:06borkdudeperhaps a better idea is to use (run! {:parallel true :lint ["lib/a" "lib/b"]})#2022-05-2314:08borkdudeI think I can repro your problem with:
user=> (require '[clj-kondo.core :as clj-kondo])
nil
user=> (do (pmap #(clj-kondo/run! {:lint [%]}) (repeat 10 src")) nil)
:/
#2022-05-2314:09borkdudeBut then again, this also doesn't work:
(do (pmap #(clj-kondo/run! {:lint [%] :cache false}) (repeat 10 src")) nil)
So how do you know it's contention on the cache?
#2022-05-2314:12borkdudeHere's the stack dump I'm seeing: https://gist.github.com/borkdude/9627c3ae595c2595e75e711d633d8fdc#2022-05-2314:14grzmI was seeing this error Clj-kondo cache is locked by other thread or process. and assumed it was due to locking of the cache file?#2022-05-2314:15borkdudeyes, but one thread shouldn't hold it so long that other threads can't access it, unless you have many many threads#2022-05-2314:16grzmYeah, there are 70+ modules with a 6-core box, so there are potentially a lot of threads.#2022-05-2314:16borkdudeoh lol, I just forgot a closing ", this works fine :)
(do (pmap #(clj-kondo/run! {:lint [%] :cache false}) (repeat 10 "src")) nil)
nil
#2022-05-2314:18borkdudeIt still works for me for 100#2022-05-2314:18borkdudeNow I'll try 1000 and perhaps I'll trigger the error#2022-05-2314:18borkdudewe should maybe make this time out configurable#2022-05-2314:18borkdudethere is a back-off mechanism#2022-05-2314:19borkdudeOh right, with 10 I can trigger it but I should not set the cache to off user=> (do (doall (pmap #(clj-kondo/run! {:lint [%]}) (repeat 10 "src"))) nil) Execution error at clj-kondo.impl.cache/sync-cache (cache.clj:166). Clj-kondo cache is locked by other thread or process.#2022-05-2314:20borkdudeCheck defmacro with-cache#2022-05-2314:20borkdude
(loop [retry# 0
                  backoff# 25]
             (if-let [lock#
                      (try (.tryLock channel#)
                           (catch java.nio.channels.OverlappingFileLockException _#
                             nil))]
               (try
                 
#2022-05-2314:21grzmYup. I’ll take a look. With :cache false you didn’t run into that issue, correct?#2022-05-2314:22borkdudecorrect#2022-05-2314:24grzmCool. I’ll play around with this. Cheers!#2022-05-2314:24borkdudeYou can also turn on :skip-lint true if you're not interested in lint warnings#2022-05-2314:24borkdudeThis might speed up things a little bit#2022-05-2314:25grzmI run it all, baby. java-class-* stuff, too 🙂#2022-05-2314:25borkdudeok#2022-05-2406:43Bart Kleijngeld(This is probably a beginner question, so if it's better suited for #beginners let me know.)
Invalid keyword: .      clj-kondo(syntax)
1. Why is this considered invalid? Clojure seems to handle it just fine. 2. If it's a matter of preference by the linter, then: a. Why it this a bad idea? b. If I would want to, is there a way to configure clj-kondo to be okay with this? Loving clj-kondo as essential part of my workflow, thanks!
#2022-05-2406:52borkdudeGoogle for Clojure reader and go to the keyword or symbol section. There it says that they can only contain one slash to separate the namespace and name part. On the phone right now, can send the link later.#2022-05-2406:52borkdudeThanks :-)#2022-05-2407:01Bart KleijngeldYes, I did read the documentation. You're referring to: > '/' has special meaning, it can be used once in the middle of a symbol to separate the namespace from the name Personally I'd say "only once" would've been clearer, but it seems pretty clear that you're interpretation is shared by everyone I read. Interestingly though, Clojure is perfectly fine with these keywords, which perhaps does point to my interpretation that "can be used once" doesn't imply that it cannot be used more than once. What do you think?#2022-05-2407:02borkdudeIt might not work in ClojureScript or babashka which has a different reader implementation #2022-05-2407:03borkdudeIn general the reader accepts more than what is specified and this may change any time, don't rely on it#2022-05-2407:04Bart KleijngeldAlright. So even if I exclusively use Clojure, you'd discourage this#2022-05-2407:05borkdudeYes#2022-05-2407:05Bart KleijngeldThanks for the quick responses and clarification!#2022-05-2411:59borkdudeHere is an example from CLJS:
$ plk
ClojureScript 1.10.914
cljs.user=> :
Syntax error reading source at (<cljs repl>:1).
Invalid keyword: :.
#2022-05-2415:01Joshua SuskaloI'm really curious what the usecase was that you had wanted to store a uri in a keyword.#2022-05-2415:03borkdudeI've had this use case in a job once, where we did stuff with RDF#2022-05-2415:03borkdudeAnd transit didn't complain on the front-end, but if you type this as a literal in CLJS, it crashes. The docs say it isn't supported so it's probably better keep as string.#2022-05-2415:03Joshua Suskaloright, but I don't quite get why it would be more appropriate to use a keyword than a string, even in theory.#2022-05-2415:04borkdudeSome maps have these things as keys and they would be automatically converted#2022-05-2415:04Joshua Suskaloah, right#2022-05-2415:35Bart KleijngeldYes, it's exactly that @U04V15CAJ. In fact, you may be thinking of the library I'm using (https://github.com/ont-app/vocabulary) which provides maps like that. Btw, the library provides tools I wasn't aware of which circumvents the issues. By using keyword-for , the passed in URI is escaped to the extent necessary to be found valid by the reader. This way you never run into issues besides potential loss of readability in your data.#2022-05-2407:05borkdudeYes#2022-05-2614:48borkdudeHere is a demo of the upcoming :warn-on-reflection linter. https://twitter.com/borkdude/status/1529836621918502913 Feedback welcome#2022-05-2614:52borkdudeMerged to master now in case anyone wants to try#2022-05-2619:56borkdudeI just pushed a clj-kondo.hooks-api namespace to master which should make it easier to play around with :analyze-call hooks in the JVM REPL. Example:
$ clj
Clojure 1.11.0
user=> (require '[clj-kondo.hooks-api :as api])
nil
user=> (def node (api/parse-string "(+ 1 2 3)"))
#'user/node
user=> (defn my-hook [{:keys [node]}] {:node (api/list-node (list* (rest (:children node))))})
#'user/my-hook
user=> (str (:node (my-hook {:node node})))
"(1 2 3)"
cc @lee
#2022-05-2622:31Noah BogartOh hell yeah, this is gonna be so helpful! #2022-05-2619:57borkdude➡️ 🚨 I plan to do a new clj-kondo release tomorrow morning. Please give master a spin if you're able to. 🚨 ⬅️#2022-05-2621:26borkdudecc @UKFSJSM38#2022-05-2621:26borkdudecc @UQTHDKJ8J#2022-05-2620:50wilkerluciohello, I'm trying to figure how to generate the kondo analisys, but having a hard time to find an example#2022-05-2621:03borkdudeHi! Have you read this already? https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#2022-05-2621:04wilkerlucioI tried to change my config but I can't see the output file, I think a complete example would be very helpful#2022-05-2621:05wilkerlucioI have questions like: • what command will make the output be generated, its just clj-kondo --lint ...? • where the output file is going to be? what is its name?#2022-05-2621:05wilkerluciooh, sorry, scrolling down I'm starting to see more complete examples, I was in a pairing session and for some reason I missed it facepalm#2022-05-2621:06borkdudeyeah, so the output is always spit out as data, never to a file#2022-05-2621:06borkdudeand you have to select either :format :edn or :format :json on the command line#2022-05-2621:08borkdudeA basic example:
$ clj-kondo --config '{:analysis true :output {:format :edn}}' --lint - <<< '(inc 1)'
{:findings [], :summary {:error 0, :warning 0, :info 0, :type :summary, :duration 36, :files 1}, :analysis {:namespace-definitions [], :namespace-usages [], :var-definitions [], :var-usages [{:fixed-arities #{1}, :end-row 1, :name-end-col 5, :name-end-row 1, :name-row 1, :name inc, :filename "<stdin>", :from user, :col 1, :name-col 2, :end-col 8, :arity 1, :row 1, :to clojure.core}]}}
#2022-05-2621:09wilkerlucioI'm trying on a project, but getting blank results:#2022-05-2621:09wilkerlucio
clj-kondo --lint src --config '{:output {:format :edn}, :analysis true}'
{:findings [], :summary {:error 0, :warning 0, :info 0, :type :summary, :duration 220, :files 26}}
#2022-05-2621:10wilkerlucio(also got blank on your example here, trying to bump clj-kondo to see if that fixes it)#2022-05-2621:10wilkerlucio
clj-kondo --config '{:analysis true :output {:format :edn}}' --lint - <<< '(inc 1)'
{:findings [], :summary {:error 0, :warning 0, :info 0, :type :summary, :duration 10, :files 1}}
#2022-05-2621:11wilkerluciobumped to latest, still seeing blank results#2022-05-2621:13borkdudeah got it#2022-05-2621:13borkdudein the previous release, put the :analysis section inside the :output#2022-05-2621:14borkdudethe master version (will be released tomorrow) supports both#2022-05-2621:14wilkerlucioah, that works! 😄#2022-05-2621:16wilkerluciothanks @U04V15CAJ 🙏#2022-05-2710:14borkdudeclj-kondo v2022.05.27#2022-05-2715:33dpsuttonjust upgraded clj-kondo and not seeing line numbers in lots of lint warnings. Details in thread#2022-05-2715:33dpsutton
clj-kondo --lint src:shared/src
src/metabase/api/activity.clj::: warning: redundant do
src/metabase/api/alert.clj::: warning: redundant do
src/metabase/api/automagic_dashboards.clj::: warning: redundant do
src/metabase/api/bookmark.clj::: warning: redundant do
src/metabase/api/card.clj::: warning: redundant do
src/metabase/api/collection.clj::: warning: redundant do
src/metabase/api/dashboard.clj::: warning: redundant do
src/metabase/api/database.clj::: warning: redundant do
src/metabase/api/dataset.clj::: warning: Redundant let expression.
src/metabase/api/dataset.clj::: warning: redundant do
src/metabase/api/dataset.clj:67:7: warning: Redundant expression: nil
src/metabase/api/dataset.clj:164:5: warning: Redundant expression: nil
#2022-05-2715:33dpsuttonthese redundant do’s seem new and give no indication where they are from. perhaps some macro or hook but it’d still be nice to have some indication of where they start#2022-05-2715:34dpsuttonredundant expression: nil seems strange but at least it has a line number#2022-05-2715:35borkdudeAh crap#2022-05-2715:35borkdudeI'll take a look later#2022-05-2715:36borkdudeI changed the hooks API and thought I improved things but I might have screwed up something#2022-05-2716:01borkdudeok, going to look now#2022-05-2718:11borkdudeReleasing a fix now#2022-05-2718:44borkdudeDone#2022-05-2720:12lreadLet that be a lesson! Never ask me to help review a PR again. simple_smile#2022-05-2720:13dpsuttonbugs get through 🙂 and two sets of eyes are always better#2022-05-2720:24dpsuttonand it appears fixed on our codebase. thanks all!#2022-05-2718:48borkdudeDeveloping hooks in the REPL should now be easier! https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#developing-hooks-in-the-repl#2022-05-2722:14ambrosebsJust bumped a really old clj-kondo dep and the def + fn linter caught some bugs. thanks @borkdude! https://github.com/clj-kondo/clj-kondo/issues/1410#2022-05-2722:33snoeIs there a linter for using a fn without calling it in the left side of a cond or cond-> like (defn add-secret? [] ...) (cond-> {} add-secret? (assoc :secret "oops")) #2022-05-2908:39borkdudeCurrently not, but issue + PR welcome#2022-05-2805:38johnIs it possible for kondo to auto-import configs from libraries that have kondo configs?#2022-05-2805:46seancorfieldI thought it did that automatically...?#2022-05-2805:49johnI thought it was going to, a few months ago. I might just be exporting wrong.
#2022-05-2805:51johnI've added the "resources" folder to my deps.edn :path vector, per the docs. Here's my project https://github.com/johnmn3/dispacio#2022-05-2805:52johnnevermind, I just had to restart vscode#2022-05-2806:02johnI guess the last issue I have is that my defmethod lint-as thing is not taking effect on subsequent instances of the defined methods:#2022-05-2806:02johnIs the only to handle that with hooks?#2022-05-2806:04seancorfield:lint-as should work I think... That's how I do it in Expectations.#2022-05-2806:06johnHere's my config.edn: https://github.com/johnmn3/dispacio/blob/master/resources/clj-kondo.exports/net.clojars.john/dispacio/config.edn I'm a little scared to bite off implementing a hook. I tried making one that wrapped the body in a do and added a (declare the-thing-name) at the top of the do form, but I couldn't get it to work#2022-05-2806:10seancorfieldHmm, here's what I have in Expectations: https://github.com/clojure-expectations/clojure-test/blob/develop/.clj-kondo/com.github.seancorfield/expectations/config.edn -- completely different path to what you have.#2022-05-2806:11seancorfieldHmm, according to the docs, your path is correct. No idea, sorry.#2022-05-2806:12seancorfieldOh, wait, I have it there as well https://github.com/clojure-expectations/clojure-test/blob/develop/resources/clj-kondo.exports/com.github.seancorfield/expectations/config.edn#2022-05-2806:14johnhmm, maybe you can't have a :lint-as and a :linters config for the same symbol#2022-05-2806:16johnhmm, not sure. Thanks for checking @U04V70XH6#2022-05-2806:24borkdudeI think using a hook is a better option here than linting as + repressing unresolved symbols #2022-05-2806:26borkdudeI'll try locally when I'm at the keyboard #2022-05-2808:24borkdude@U050PJ2EU Made a pull request which fixes the above issues. You can execute clj-kondo --lint .clj-kondo/test.clj to see that it works, with the newest clj-kondo.#2022-05-2808:24borkdudehttps://github.com/johnmn3/dispacio/pull/2#2022-05-2814:49john@U04V15CAJ There might be an issue with the paths#2022-05-2814:50johndispacio/dispacio?#2022-05-2814:50johngoing to try to remove one level of dispacio#2022-05-2814:50borkdudeNo, this is correct#2022-05-2814:50borkdudeYou just have to use the newest clj-kondo, released yesterday#2022-05-2814:50johnaaah#2022-05-2814:51borkdudeIn the newest clj-kondo, the .clj_kondo extension is supported#2022-05-2814:51borkdudefor hook code#2022-05-2814:51borkdudeto not confuse it with application code#2022-05-2814:51borkdudeand I used that#2022-05-2814:52johnOkay. So that'll flow in from clojure-lsp at some point?#2022-05-2814:52borkdudePerhaps @UKFSJSM38 can tell you how to use the master version of clojure-lsp#2022-05-2814:52borkdudeYes. You can try with the clj-kondo vscode extension now if you want btw and disable linting in clojure-lsp#2022-05-2814:52borkdudetemporarily#2022-05-2814:54ericdalloI just pushed to master the bump of clj-kondo on clojure-lsp, if you want you can use a nightly build on #clojure-lsp-builds#2022-05-2814:55borkdudeawesome!#2022-05-2916:57lreadAm giving the clojure-lsp nightly a whirl on macOS doom emacs.#2022-05-2916:59lread@UKFSJSM38 I guess I should be viewing the new .clj_kondo files in clojure-mode?#2022-05-2917:02ericdalloProbably missing changing that on clojure-mode, right @U04V15CAJ?#2022-05-2917:02ericdalloWe should open a PR there and on other projects to consider that as a clojure file like clojure-lsp itself 😂#2022-05-2917:13lreadWhen I do switch to clojure-mode for a .clj_kondo file, I do get an odd finding for that file:#2022-05-2917:13lreadThis could entirely me just being emacs-naive and not doing some more setup/config?#2022-05-2917:22ericdalloIIRC that can't parse comes from kondo, probably we need to consider .clj_kondo files as clj ones as well there#2022-05-2917:50lreadBut the .clj-kondo hook files are being picked up and used for linting. And the enhanced macroexpand hook behaviour seems to be pinpointing errors at their location.#2022-05-2917:51ericdalloDo you repro that if you use latest kondo and lint manually that file via CLI?#2022-05-2917:55lreadGood question… Here’s the hook source:
(ns etaoin.impl.util)

(defmacro defmethods
  "Declares multimethods in batch. For each dispatch value from
  dispatch-vals, creates a new method."
  [multifn dispatch-vals & fn-tail]
  `(doseq [dispatch-val# ~dispatch-vals]
     (defmethod ~multifn dispatch-val# 
And here’s me linting from the cmdline:
❯ clj-kondo --version
clj-kondo v2022.05.29
❯ clj-kondo --lint .clj-kondo/hooks/etaoin/impl/util.clj_kondo 
.clj-kondo/hooks/etaoin/impl/util.clj_kondo:11:26: warning: unused binding prefix
.clj-kondo/hooks/etaoin/impl/util.clj_kondo:11:33: warning: unused binding suffix
linting took 12ms, errors: 0, warnings: 2
#2022-05-2917:55lreadSo, the answer is: no.#2022-05-2917:56borkdudePerhaps clojure-lsp is passing a wrong --lang clj_kondo or so#2022-05-2917:57ericdalloHum, probably, I will take a look soon#2022-05-2917:58lreadYup, I think borkdude is onto something there:
❯ clj-kondo --lint .clj-kondo/hooks/etaoin/impl/util.clj_kondo --lang clj_kondo
.clj-kondo/hooks/etaoin/impl/util.clj_kondo:0:0: error: Can't parse .clj-kondo/hooks/etaoin/impl/util.clj_kondo, No matching clause: :clj_kondo
linting took 6ms, errors: 1, warnings: 0
#2022-05-2917:59lreadMaybe lsp is passing in --lang :unknown ?#2022-05-2917:59borkdudeNot pass any --lang ... probably, unless you know what you're doing ;)#2022-05-2918:00borkdudelang defaults to clj if you don't pass anything and the extension is unknown#2022-05-2918:04lreadAnd my example above shows that I will leave in lint warnings without clj-kondo/lsp help. I am totally dependent.#2022-05-2918:09ericdalloI'll change to not pass lang#2022-05-2918:11lread@U04V15CAJ does it make sense to lint hooks code? I guess so, but would like a borkpinion.#2022-05-2918:12lreadMaybe call hooks more so than macroexpand hooks?#2022-05-2918:13borkdudeI think it makes sense to lint it while developing those#2022-05-2918:13borkdude@UKFSJSM38 It depends how you are calling clj-kondo. If you pass just stdin text without a filename, then clj-kondo cannot guess the language, so you can give a hint --lang cljs or so#2022-05-2918:14borkdudeBut if you just pass the filename with the extension, then clj-kondo will derive the language from that#2022-05-2920:18ericdalloJust pushed the fix on clojure-lsp#2022-05-2920:18borkdudeAwesome!!!#2022-05-2923:07lreadJust gave it a go @UKFSJSM38, my .clj-kondo files are no longer producing lint warnings!#2022-05-2908:39borkdudePushed a few small updates: https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#20220529#2022-05-3114:56Noah BogartAt my job, we have a lot of test assertions inside of let blocks:
(let [stuff (do-stuff a b c)
      _ (is (= 1 stuff))
      _ (is (= 2 (inc stuff)))
     other-stuff (do-more-stuff x y z)]
  (is (= 3 other-stuff)))
Merely to avoid having to nest let blocks. (Sometimes, the only test assertions are inside of let blocks lol) I think this a code smell and have written up a hook to warn on this. Would you be interested in this as an official lint?
#2022-05-3114:57borkdudeNo, I like this ;)#2022-05-3114:57Noah Bogartlol okay#2022-05-3114:58borkdudeBut maybe other people are interested and then I would be okay with adding an optional linter. I'll keep it in mind. Let's wait for this to come up more often, it's the first time I hear someone perceive this as a problem#2022-05-3115:00Noah BogartYeah, it's not bad necessarily, it's just not how I think it should be done and I find it hard to work with (because I can't write normal test stuff, I have to be aware of when I'm inside of a let block and add dummy binds _ , etc). Would you like me to open a github issue about this?#2022-05-3115:02borkdudeYes, and then others could comment on that, that's fine#2022-05-3118:39seancorfieldFWIW, we have 85 of these in our work codebase. It's a pretty convenient way to provide inline assertions in complex tests.#2022-05-3119:53Noah BogartYeah, I wouldn't suggest this to be on by default, but it does seem worth having as a toggle for those who care.#2022-05-3119:56borkdudeI sometimes even prefer this style to not get deeply nested expressions#2022-06-0303:33jacob.maineAnyone ever tried https://github.com/Engelberg/better-cond for this sort of thing? It’s advertised as being good at both avoiding rightward drift and sprinkling in side effects#2022-06-0303:37seancorfield@U07M2C8TT I wouldn't consider better-cond as a solution to this particular "problem" -- there's no conditional work going on here.#2022-06-0303:38seancorfield(my personal feeling is that better-cond is solving the wrong problem: refactor your code, don't add a weird macro to support your bad code 🙂 )#2022-06-0303:45jacob.maine@U04V70XH6 I agree, I’d be skeptical of better-cond in the main codebase, but I feel less hesitant about using a “weird macro” in test code. I’ve never used it, I was just curious if anyone had ever used it in the style where you https://github.com/Engelberg/better-cond#minimizing-rightward-drift#2022-06-0303:47seancorfieldWow, I think that's horrific... Both versions...#2022-06-0303:47seancorfieldIt's screaming for a refactor.#2022-06-0303:52jacob.mainePerhaps, but again, we’re talking about test code, which doesn’t always get the same love. Again, I’m not advocating this style, just asking if it’s worked out for anyone. It’s clear… it wouldn’t work for you! simple_smile#2022-06-0110:26borkdudeI'm working on clj-kondo hooks workshop material now for next week's ClojureD. Is there anyone who isn't going there and wants me to help go through the material? Please give me a ping :)#2022-06-0118:14Ken AllenIs there a way to set up linting for plumbing.core/fn-> ? if I lint as clojure.core/-> I still get type and arity errors for the first form. I’d rather not exclude if I can get away with it#2022-06-0118:19borkdude@kallen I think this is a good candidate for hooks. 🧵#2022-06-0118:20borkdudeTry the :macroexpand hook: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand and see if that works for you#2022-06-0118:21borkdudeI'm working on a more gentle introduction to hooks here: https://github.com/clj-kondo/hooks-workshop-clojured-2022 This is work in progress and will be used for a workshop next week on ClojureD#2022-06-0118:32Ken AllenTIL that the version of clojure-lsp I installed from homebrew is super old. After fixing that and following the example it seems to be working. I essentially just copied the source from plumbing.core but I gather that I don’t actually need to do that if the real macro is happy being run from SCI?#2022-06-0118:42Ken Allenhmm maybe I spoke too soon. It’s not complaining anymore but emacs is now highlighting the entire (fn-> ….) form like it’s a symbol when my cursor is in it and it’s showing a gensymed symbol in the minibuffer. No idea where in the kondo->lsp->emacs chain that issue is coming from#2022-06-0118:57borkdude@kallen Hmm, can you make a repro?#2022-06-0119:07borkdude@kallen So this works for me:
(defmacro fn-> [& body]
  `(fn [x#] (-> x# 
#2022-06-0119:07borkdude
hooks-workshop.macros/fn-> hooks-workshop.macros/fn->
#2022-06-0119:07borkdudeAnd then:
(def f (fn-> inc inc))
  (f 1 2)
gives a lint warning about calling f with an incorrect amount of args (which is expected)
#2022-06-0119:10borkdude#2022-06-0119:13borkdudeSo how are you calling fn->?#2022-06-0119:43Ken Allento be clear it does lint correctly now. if I do (fn-> str inc) it complains that it’s getting a string when it expects a number#2022-06-0119:45Ken AllenWhat I’m seeing is that now clojure-lsp seems to think the entire fn-> form is a symbol so it highlights it and puts the symbol at the bottom, just like if I had put my cursor on def#2022-06-0120:10borkdudeYeah, this is an artifact of :macroexpand . If you want more precise linting, use :analyze-call#2022-06-0120:10borkdudewhich isn't that hard with a macro like this#2022-06-0120:11borkdudeTomorrow I'll write part 3 of the workshop which should hopefully help ;)#2022-06-0120:12borkdudeBut the docs about it should be good too#2022-06-0120:50Ken AllenI think I get the picture of what is needed from the docs but you might have the workshop part written by the time I get to poking at this tomorrow.#2022-06-0120:51Ken Allenis there a good way to distribute this sort of config? plumbing is a pretty popular library. Or is the idea that they become part of the library itself?#2022-06-0120:52Joshua SuskaloYou can make a PR to put it in the config exports in the library's resources.#2022-06-0120:52Joshua SuskaloI think there's a community project to distribute them too if the library owner refuses to accept a PR to make it part of their library exports.#2022-06-0120:53borkdudeYes: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration Here are some examples :) https://github.com/clj-kondo/clj-kondo/discussions/1528#2022-06-0120:53borkdudeI think we have a fair chance of getting this into plumbing, since @U055XFK8V is a maintainer there#2022-06-0120:54borkdudeThe community project is https://github.com/clj-kondo/config#2022-06-0120:55borkdudeBut it's currently not fine-grained, it imports all of those which isn't really optimal#2022-06-0120:56borkdudeSplitting up into separate deps could work#2022-06-0120:56borkdudeAnyway, it's best to send the configs to the source library#2022-06-0121:01Ken Allencool, if I get analyze-call working and I get a free moment I’ll PR up at least the stuff that I use on a regular basis. Hopefully that will provide a kernel to grow from.#2022-06-0120:43JHi guys! Is there a way to detect that (inc pokemon) is incorrect (like (inc "1")) because pokemon has a Pokemon schema?#2022-06-0120:46borkdudeI think theoretically that should be possible since Pokemon is, at minimum, a map right?#2022-06-0120:46borkdudeE.g. this does warn:
(let [x {}]
  (inc x))
#2022-06-0120:47JYes pokemon is a map#2022-06-0120:48borkdudeSo if you could make a repro using pure clj-kondo, and post an issue about it, we can see why it's not working and how it can be fixed#2022-06-0217:39hiredmanit seems like kond doesn't understand how recur works inside a deftype/defrecord inline protocol extension or interface implementation. when you recur in those you don't pass the this argument, which kondo flags as an error#2022-06-0217:40hiredmanI don't see any existing issues on github for this, but describing it in a search term is tricky#2022-06-0217:41borkdude@U0NCTKEV8 Can you make an example of this?#2022-06-0217:41dpsutton#2022-06-0217:42dpsutton
(defprotocol CountDown
  (count-down [_ n]))
(count-down
 (reify CountDown
   (count-down [_ n] (if (zero? n) :done (recur (dec n)))))
 5)
#2022-06-0217:42borkdudeHmm, this works:
(defprotocol IFoo (-foo [_]))
(defrecord Foo [] IFoo (-foo [x] (recur x)))
#2022-06-0217:43hiredman
(deftype Foo [] java.lang.Runnable (run [this] (recur)))
gets flagged for example
#2022-06-0217:44hiredman
user=> (defprotocol IFoo (-foo [_]))
(defrecord Foo [] IFoo (-foo [x] (recur x)))
IFoo
user=> Syntax error (IllegalArgumentException) compiling recur at (REPL:1:34).
Mismatched argument count to recur, expected: 0 args, got: 1
user=>
`
#2022-06-0217:44hiredmandoesn't work#2022-06-0217:45borkdudeFor now you can use #_:clj-kondo/ignore before the false positives to suppress it#2022-06-0217:47borkdudeSo I think these are all related:
(defprotocol IFoo (-foo [_]))
(defrecord Foo [] IFoo (-foo [x] (recur)))
(deftype Foo [] java.lang.Runnable (run [this] (recur)))
(reify IFoo (-foo [_] (recur)))
The recur arity should be one less in protocol method implementations
#2022-06-0217:48borkdudeI'll make an issue for this#2022-06-0217:49borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1714#2022-06-0217:49borkdudeThanks for reporting#2022-06-0217:50hiredmanthanks for creating the issue, I was flailing around in the template still#2022-06-1910:06borkdudeFixed on master#2022-06-0716:30Alexis VincentWhat are the conventions around committing directories in the .clj-kondo dir? Haven’t been able to find something discussing this#2022-06-0716:30borkdude@mail024 The convention is to commit the configs for the projects you're using inside your project so nobody else has to repeat the installation and sees the same linting results#2022-06-0716:31Alexis Vincentcool thanks. So add .clj-kondo, but ignore .cache?#2022-06-0716:31borkdudeyeah#2022-06-0716:31Alexis Vincentis cache the only dir to ignore?#2022-06-0716:31borkdudeYes - If you add .cache to gitignore it will work correctly for clojure-lsp too#2022-06-0716:32Alexis Vincentcool thanks 🙏#2022-06-0716:32Alexis Vincentoh you mean .lsp is normally committed as well? just without cache?#2022-06-0716:33borkdudeyeah, .lsp supports a similar config.edn file and any temporary stuff goes into .cache#2022-06-0716:33Alexis Vincentah right, thanks#2022-06-0910:40ikitommihow can I disable warning for unused imports? have user.clj with:
(ns user
  (:require [integrant.repl :refer [clear go halt prep reset reset-all]]
            [integrant.repl.state :as state]))
, which causes (for all of the unused ones):
... warning: #'integrant.repl/clear is referred but never used
#2022-06-0910:46borkdude@ikitommi
{:config-in-ns {user {:linters {:unused-referred-var {:level :off}}}}}
#2022-06-0910:46ikitommithat’s good, thanks!#2022-06-0916:20jakemccThis would probably be more obvious if I had a dependency that provided a clj-kondo config as I could see what the steps are doing but do steps 3 and 4 of the https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#importing section only need to be done with a dependency changes? Results of both committed to your own repo or only step 3?#2022-06-0921:08Joshua SuskaloHas there been a lint considered for putting type hint for return values of protocol definitions on the arglist instead of on the method name like you're supposed to do?#2022-06-0921:25borkdude@suskeyhose There is a linter which does this for normal functions - perhaps it already works for protocol implementations? not sure#2022-06-0921:25Joshua Suskaloyeah, but it has kinda the opposite requirement#2022-06-0921:26Joshua Suskalo
(defn blah ^return [arg1 arg2] ...)
(extend-protocol Blah
  Type
  (^return method [arg1 arg2] ...))
#2022-06-0921:27borkdude@didibus already posted an issue about this. References to official Clojure docs would be useful and then we can make a linter#2022-06-0921:27borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1717#2022-06-0921:28Joshua SuskaloSounds good#2022-06-0921:29Alex Miller (Clojure team)deftype and defrecord inline method impls for sure#2022-06-0921:29Alex Miller (Clojure team)probably reify too#2022-06-0921:30Alex Miller (Clojure team)https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/deftype
Method definitions take the form:

(methodname [args*] body)

The argument and return types can be hinted on the arg and
methodname symbols.
#2022-06-0921:31Alex Miller (Clojure team)yeah, also in reify docstring#2022-06-0921:36Alex Miller (Clojure team)not sure what happens with extend-... - those get expanded into extend calls which don't really have the method name as a symbol anymore, not sure if that type hint is retained anywhere, probably not by just glancing at the code#2022-06-0921:37Alex Miller (Clojure team)I guess there's not really any need for protocols, only for Java interfaces to satisfy the type gods#2022-06-1010:16pinkfrogI know this must have been brought up before. But I’d like to know, what’s the current solution of linting on rum.#2022-06-1010:23borkdude@UGC0NEP4Y Check out: https://github.com/clj-kondo/config#installation#2022-06-1013:55pinkfrogThanks. Works like a charm.#2022-06-1111:47borkdudeWorkshop time at ClojureD! https://github.com/clj-kondo/hooks-workshop-clojured-2022 EDIT: done#2022-06-1114:28borkdudeHere are some possible solutions from the clj-kondo clj-kondo hooks workshop! https://github.com/clj-kondo/hooks-workshop-clojured-2022/tree/solutions cc @U3ZG4CAF8#2022-06-1112:46pavlosmelissinosIs there any chance I could make clj-kondo warn me that this: (concat v1 (if cond ["new item"] [])) can be rewritten as (concat v1 (when cond ["new item"]))? My instinct tells me no but then again I saw clj-kondo do some type inference magic the other day, so I wouldn't be surprised 🙂 edit: oops, bad timing#2022-06-1207:21borkdudeIf you couldn't attend https://twitter.com/hashtag/clojured?src=hashtag_click but are still interested in the clj-kondo workshop, you can do it in a self-paced way here: https://github.com/clj-kondo/hooks-workshop-clojured-2022https://t.co/roZn5rJ1Q1 Feel free to drop questions here. The solutions are in the solutions branch.#2022-06-1613:05mpenetI saw some weird error today: Can't parse blablabla.clj, No implementation of method: :tag of protocol: #'clj-kondo.impl.rewrite-clj.node.protocols/Node found for class: nil - clj-kondo#2022-06-1613:05mpenetdoes that ring a bell?#2022-06-1613:05mpenetit flags a ns declaration#2022-06-1613:06mpeneta very simple one: (ns something.something), no require/refer-clojure & co#2022-06-1613:07mpenettried to nuke the .lsp cache & the clj-kondo one, still here#2022-06-1613:08borkdudeplease try with the most recent version of clj-kondo on the command line, to avoid any downstream involvement#2022-06-1613:09borkdudecan't repro using this example alone:
(ns something.something)
#2022-06-1613:09mpenetthis is not the real namespace I have, but I think the ns name is irrelevant in that case#2022-06-1613:10borkdudeis it possible to make a minimal repro though and do it with clj-kondo on the command line and send that repro here?#2022-06-1613:10mpenet❯ clojure-lsp --version clojure-lsp 2022.05.31-17.35.50 clj-kondo 2022.05.31#2022-06-1613:10mpenetstill here#2022-06-1613:11mpenetI ll check on the command-line#2022-06-1613:11mpenetsame error on the cli#2022-06-1613:12borkdudecan you show me your CLI invocation?#2022-06-1613:13mpenet❯ clj-kondo --lint . ./some-random-file.clj:0:0: error: Can't parse ../some-random-file.clj, No implementation of method: :tag of protocol: #'clj-kondo.impl.rewrite-clj.node.protocols/Node found for class: nil#2022-06-1613:13mpenetsame result with ❯ clj-kondo --cache false --lint .#2022-06-1613:13borkdudewhat is in some-random-file.clj?#2022-06-1613:14mpenetprotocols & implems of these etc etc, but the problem lies here. If I remove half of the code the issue goes away, I ll try to bisect the thing until I find the culprit#2022-06-1613:15mpenetah found it#2022-06-1613:15mpenetthere was a buggy defmulti#2022-06-1613:15mpenetit had no dispatch fn defined, something like (defmulti foo)#2022-06-1613:16mpenetodd that I got pos 0:0 flagged tho#2022-06-1613:16mpenettry with a file with that:#2022-06-1613:16mpenet
(ns foo)

(defmulti foo)
#2022-06-1613:16mpenetyou'll get the same issue#2022-06-1613:17borkdudeaaah ok#2022-06-1613:17borkdudeyes, when something unexpected happens, then clj-kondo doesn't know where to put the issue and it just puts it at 0:0#2022-06-1613:17borkdudebut we should make this more robust. feel free to post an issue#2022-06-1613:18mpenetsure#2022-06-1613:23borkdudethanks#2022-06-1615:00delaguardoIs it possible to discourage usage of whole namespace? I know there is https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#discouraged-var but would be great to place the warning directly on ns declaration because requiring namespace is a mutation and might cause some problems even if vars are not used#2022-06-1615:03borkdudeCurrently not but feel free to post an issue#2022-06-1615:04delaguardowill do#2022-06-1615:05borkdudeI think there were also some requests recently to lint access from namespace X to namespace Y etc#2022-06-1615:05borkdudewhich might also be nice to incorporate#2022-06-1615:14Alex Miller (Clojure team)you can deprecate in the namespace metadata#2022-06-1615:14Alex Miller (Clojure team)https://github.com/clojure/clojure/blob/master/src/clj/clojure/parallel.clj#L9 for example#2022-06-1615:15Alex Miller (Clojure team)I guess that's not actually metadata, but it could be#2022-06-1615:16Alex Miller (Clojure team)that's proposed in https://clojure.atlassian.net/browse/CLJ-706 (not sure if that will ever get looked at, Rich was noncommittal the last time he did)#2022-06-1615:16delaguardohttps://github.com/clj-kondo/clj-kondo/issues/1721 issue filed 🙂#2022-06-1615:18delaguardo@U064X3EF3 those namespaces out of my control. They are coming from a library and to alter metadata I have to load it first which is exactly what I'm trying to avoid.#2022-06-1615:21Alex Miller (Clojure team)gotcha#2022-06-1615:23borkdudeThanks! There's also already an issue for warning on deprecated ns metadata#2022-06-1710:13delaguardoFWI - https://github.com/clj-kondo/clj-kondo/pull/1724 @U04V15CAJ adding new linter was surprisingly easy, kudos for the architecture of kondo#2022-06-1710:19borkdudeNice. Maybe we should add some example of using an ns group + the in option? Maybe :from is a better name than :in ?#2022-06-1710:24delaguardoIn my head in emerged from the sentence: "In namespaces #{X Y Z} discourage usage of namespace A" can't make such sentence with from but probably it is a problem of my english 🙂#2022-06-1710:25borkdudeWe already use the word :from in the analysis here: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md so imo that would be more consistent#2022-06-1710:25borkdudeThe namespace A is used from namespaces X Y Z. Valid English I think?#2022-06-1710:41delaguardosounds right to me, I'll change it#2022-06-1809:30borkdude@U04V4KLKC I invited you to #clj-kondo-dev for some PR feedback#2022-06-1809:31delaguardoThanks!#2022-06-1712:26nottmeyWould be nice to have a lint rule for that, often I don’t notice whether I use a function or a macro… (but ofc when executing you notice things like this directly)#2022-06-1713:03borkdudeI think that would be useful, feel free to post an issue#2022-06-1713:14nottmeyok nice, will do ☺️#2022-06-1713:50nottmeydone: https://github.com/clj-kondo/clj-kondo/issues/1725#2022-06-1713:51borkdudethanks#2022-06-1716:03markaddlemanI'm a new clj-kondo user through Clojure Extras Intellij plugin. I'm really enjoying it. I think clj-kondo doesn't properly understand sequence when used with transducers in a multi-arity situation. For example:
(sequence (map (fn [i j]))
  (range 10) (range 10))
clj-kondo reports fn is called with 1 arg but expects 2 I didn't see a github issue for this. Should I open one?
#2022-06-1716:03borkdude@markaddleman Good catch, please open an issue#2022-06-1716:07markaddlemanhttps://github.com/clj-kondo/clj-kondo/issues/1726#2022-06-1716:03borkdudeDo you know how to ignore the error already?#2022-06-1716:04markaddlemanI know it can be done but I haven't delved into kondo's config very deeply#2022-06-1716:05borkdudeok, you can just put a #_:clj-kondo/ignore in front of the form until it's fixed#2022-06-1716:05markaddlemanoh, cool. I didn't know about that approach.#2022-06-1819:57borkdudeSome people have asked for merch for my OSS projects (stickers, t-shirts). Here's a link to all the products: https://clojurians.slack.com/archives/CLX41ASCS/p1655582061874859?thread_ts=1655492617.008949&amp;cid=CLX41ASCS#2022-06-1913:11Ben SlessIs there a way to ignore comment blocks for analysis?#2022-06-1913:13borkdudeyes, :skip-comments true#2022-06-1913:13borkdudeA more recommended config is :config-in-comment {...} though, so you will still get linting, but can disable things#2022-06-1913:54Ben SlessNice, thanks!#2022-06-1914:59borkdudeThe next release of clj-kondo will suppress redundant do in .cljc files if it's not redundant in one language branch. E.g.:
(do #?(:clj (+ 1 2 3)) (+ 4 5 6))
will no longer give a warning, although it would be redundant in the :cljs case
#2022-06-2016:34uwoIs there a way to suppress all warning level linters with the --config flag? I'm having trouble finding it if there is..., e.g. git ls-files -m | xargs clj-kondo --config '{:output {:level :error}}' --lint#2022-06-2016:35borkdude@uwo --fail-level <level>#2022-06-2016:35borkdudebut this is only for affecting the exit code#2022-06-2016:36uwothat's still reporting warnings for me. ah, right, I'm just using this for the ouput not the exit code#2022-06-2016:36borkdudeI guess you can use grep for now and post an issue (there might already be one for this I vaguely remember)#2022-06-2016:37uwoYeah, I think there's a stale issue, but it's not a big problem to use grep. Thanks for the help!!#2022-06-2016:38borkdudeComment on the issue if you want to revive it#2022-06-2016:38uwosince this can already be resolved with grep, I don't want to add to the number of things for you to juggle 🙂#2022-06-2016:38borkdudeBtw it's also possible to output EDN and then process it using e.g. babashka or clj or jet#2022-06-2016:54borkdude
$ clj-kondo --lint src --config '{:output {:format :edn}}' | jet -q ':findings (filter (= (quote :error) :level))'
#2022-06-2016:55borkdudeor:
$ clj-kondo --lint src --config '{:output {:format :edn}}' | jet -t ':findings (filter #(= :error (:level %)))'
#2022-06-2020:39uwoNice!!#2022-06-2020:42uwoOn another topic, I see that support for compojure macros is built in to clj-kondo. I'm running the most recent version of clj-kondo available thru brew. Is there an obvious place where I might have misconfigured things? All my defroutes are not being linted as def#2022-06-2020:44borkdude@uwo can you be more specific? compojure support is indeed built-in so you should not have to configure anything#2022-06-2020:45uwoSorry, that was a confusing statement on my part. I figured i would't need to configure anything, but all the compojure macros are showing up as lint errors.#2022-06-2020:45borkdudeIs this compojure.core or some derivate like compojure-api?#2022-06-2020:46uwoahhh, compojure-api#2022-06-2020:46borkdudeyeah, that's not built in#2022-06-2020:49uwoThank you again!#2022-06-2107:20borkdudeReleasing a new version tomorrow: https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#unreleased https://github.com/clj-kondo/clj-kondo/releases/download/untagged-2f17ed841a5a4292a983/clj-kondo-2022.06.01-SNAPSHOT-macos-aarch64.zip Please test if you can (cc @ericdallo)#2022-06-2208:52borkdudeNew clj-kondo release. Check #announcements#2022-06-2210:28ingesolI have a function schema like this:
{:malli/schema [:=> [:cat :some-type [:maybe :coordinates]] :some-other-type]}
When I generate clj-kondo config for it, it generates an {:op :keys} for it, which is not nilable. So when a caller passes explicit nil to it, it produces a linter warning. Is this expected? I could do [:or :coordinates :nil] , but that produces :any in clj-kondo, which is far less useful for linting.
#2022-06-2210:29borkdudeThis should probably be fixed in malli#2022-06-2210:29ingesolI just realized myself 😉#2022-06-2210:31robert-stuttafordM1 support yaaaaay#2022-06-2210:31ingesolBut how do you express a nilable map spec in clj-kondo?#2022-06-2210:34borkdude@ingesol good question, I'm going to find out now#2022-06-2210:48borkdude@ingesol Maybe it's better if malli generated :nilable/map in this case, if there are no keys specified#2022-06-2210:48borkdudeWe could also support {:op :keys :nilable true} or so#2022-06-2210:49borkdudebut that's not currently in there#2022-06-2210:54ingesol@borkdude Having the :ops spec there is very useful when there are keys specified. So :nilable support would be nice. I also realize I should have inserted my actual spec for coordinates , which is something like [:map [[:x number?] [:y number?]]#2022-06-2210:56borkdudeok, PR welcome#2022-06-2211:00borkdudeor at least an issue#2022-06-2212:29andrea.crottiI'd like to be able to show a warning when someone requires a certain library in the ns declaration. Is that something I should do with clj-kondo hooks or maybe there are even easier ways? I mean potentially even grepping could work in this particular case, but that's not really a great idea in general, would rather at least parse the code properly and grep.#2022-06-2212:30delaguardothat was release just today ) https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#discouraged-namespace#2022-06-2212:37andrea.crottihehe that's great timing#2022-06-2212:38andrea.crottiI'll try it then, incredible turnaround, getting features even before you ask for them#2022-06-2212:36plinsI have a fn that is being used only by tests (but no production code is using it) is there a way of clj-kondo to hint me about these?#2022-06-2212:40delaguardo:discouraged-var in combination with :config-in-ns should work. You might also need to declare :ns-group to separate test namespaces from production#2022-06-2212:42delaguardohttps://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#discouraged-var#2022-06-2215:28Joshua SuskaloIs there a particular reason you couldn't put this var into a test utility namespace? There's no reason that you can't have non-test vars (or even namespaces with no tests) in your tests directory.#2022-06-2220:40plinsits production code, but no one is using it yet, and I want the linter to say to me “Hey you have an unused function” this is not happening because the tests are currently using this function#2022-06-2220:41Joshua SuskaloAh I see, that's the opposite of the problem we thought it was.#2022-06-2220:41Joshua SuskaloYou can do this by just not including your tests on the path while you lint. I'm not 100% sure how you ensure that in kondo though.#2022-06-2220:42plinsI still want to lint the tests (so maybe this is a tricky one)#2022-06-2220:43Joshua SuskaloRight, the point here would be to basically run the linter twice, once on the source directory, and once on the test directory. When running it on the tests you need the source to be on the path, and when you run it on the source directory you need the tests to not be on the path.#2022-06-2220:43Joshua SuskaloI don't know if there's a convenient way to do this at the moment however.#2022-06-2319:20borkdudeCan you re-state the problem? > I have a fn that is being used only by tests (but no production code is using it) > > is there a way of clj-kondo to hint me about these? It isn't at all clear to me what the problem is. What should clj-kondo hint?#2022-06-2319:21Joshua SuskaloThis I think is actually about the clojure-lsp lint of unused public vars (@UKFSJSM38), but the problem is that vars should still be considered unused if they are used in tests.#2022-06-2319:22borkdudeyeah, this is a clojure-lsp feature#2022-06-2319:26ericdallothe issue is: how clojure-lsp know that usage is from a test and not a different source-path?#2022-06-2319:32Joshua SuskaloI think it'd just be a config option for that lint that specifies ignored directories#2022-06-2319:33ericdallosounds like a valid setting#2022-06-2405:26nixin72Hi, I’m getting this error in one of my projects at the top of every file on the ns form and I’m not sure why:
Can't parse /path/to/file.clj Configuration error. Expected fully qualified symbol, got: defn (lsp)
It looks like this is coming from clj-kondo? I’m not sure what the error message is supposed to mean in this context.
#2022-06-2406:24borkdudePerhaps a configuration error in config.edn#2022-06-2506:27borkdudeYes, the error could be in that lint-as config: no fully qualified symbols give an error #2022-06-2512:12borkdudeSo maybe you could post your config, to see if that is the case?#2022-06-2512:12borkdudeAnd/or move your config to see if this causes the problem#2022-06-2414:55gordonThe CI config for one of our projects lints the entire classpath, before then going on to lint the src and test directories. It's also trying to save/restore the cache that linting the classpath generates, presumably to decrease run time. I've observed that: 1) the presence of a cache in .clj-kondo/.cache makes no difference to the run time of lein clj-kondo --lint "$(lein classpath)" --dependencies --parallel --copy-configs. So restoring the previous .clj-kondo/.cache seems to provide no benefit. 2) the presence of the cache makes no noticeable difference to running lein clj-kondo --lint src So the net effect is that our CI job spends twice as long linting than it maybe needs to. Before I remove the part that lints the whole classpath and saves/restores .clj-kondo/.cache I'd like to check my assumptions. Should the presence of a pre-populated .clj-kondo/.cache noticeably change the run time when you are linting a project in CI?#2022-06-2512:22borkdude--dependencies is faster if you have a previous cache with jar files linted. clj-kondo will tell you that it will be faster since it prints: skipping jar such and so, because I've seen it before#2022-06-2512:22borkdude
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "63010c110807160706230e52"}, :content ("[email protected]")}
#2022-06-2512:23borkdudebut the condition is that the config.edn etc hasn't changed since last time#2022-06-2512:24borkdudeI'd say try it locally and observe the difference. There may be something off in the CI setup too#2022-06-2814:55gordonThanks @U04V15CAJ I spent more time prodding at CI to find out why the cache didn't seem to be having an effect. Your comment about config.edn was spot on. We're using CircleCI's caching for the clj-kondo cache, based on the checksum of our project.clj. What happened was a deletion from project.clj reverted it to a former state, which then led the cache restoration to restore a clj-kondo cache taken before a change to config.edn. And because CircleCI caches don't get overwritten, this older incompatible cache was constantly being used. Basing the cache off the checksum off both project.clj and config.edn does the right thing.#2022-06-2511:57peterhIs it possible to exclude a var from :unexpected-recur similar to {:linters {:unresolved-var {:exclude [foo]}}}? I am trying to use the loopr macro which was recently introduced here by @p-himik (see https://clojurians.slack.com/archives/C8NUSGWG6/p1656081475345209 ), but I get an “Unexpected usage of recur” warning from clj-kondo since it is not in tail position. I tried :unexpected-recur {:exclude [(dom-top.core/loopr)]}, but it does not seem to work.#2022-06-2511:59borkdude@peterhfmnn A better solution might be to use {:lint-as {custom.ns/loop clojure.core/loop}}#2022-06-2512:12peterhThis gets rid of the “Unexpected usage” error, but unfortunately not the “Recur can only be used in tail position” error, since there is a final form underneath the recur call. Maybe I have to build a custom hook?#2022-06-2512:13borkdudeThere is also :config-in-call where you can define a complete new configuration and disable this linter#2022-06-2512:13borkdude
:config-in-call {custom.ns/loop {:linters {:unexpected-recur {:level :off}}}}
#2022-06-2512:14borkdudeBut yeah, a hook would be the optimal solution I guess#2022-06-2512:14borkdudeIf you only use this function sporadically, you can also use #_:clj-kondo/ignore before the warning
#2022-06-2512:18peterh:config-in-call seems to work fine, thanks! Is it missing from the documentation?#2022-06-2512:19borkdudeI think so, since I included it as an experimental thing, but I guess we could document it now :)#2022-06-2512:19peterhIf I use it more often, I may write a custom hook. I did that before and it wasn’t too difficult.#2022-06-2910:32pezHi. Need some advice, here. At Pitch we want to catch a possible library usage error at development and CI time, and we wonder if we can create some clj-kondo linters for it. Here's some pseudo-ish code, the library:
(ns foo-lib.core)

(def all-things (atom #{}))

(defn init! [valid-things]
  (reset! all-things (set valid-things)))

(defn foo? [thing]
  (when-let [my-thing (all-the-things thing)] ; not finding `thing` is bad
    (figure-thing-out my-thing)))
App 1:
(ns app-1.some-ns
  (:require [foo-lib.core :as foo-lib]
            [re-frame.core :as rf]))

(def app-1-foo-things [:a])

(foo-lib/init! app-1-foo-things)

(defn hello []
  (foo-lib/foo? :a) ; valid use
  (foo-lib/foo? :b) ; invalid use
  @(rf/subscribe [:foo-lib-foo? :a]) ; valid use
  @(rf/subscribe [:foo-lib-foo? :b]) ; invalid use
  )
App 2:
(ns app-2.some-ns
  (:require [foo-lib.core :as foo-lib]
            [re-frame.core :as rf]))

(def app-2-foo-things [:a :b])

(foo-lib/init! app-2-foo-things)

(defn hello []
  (foo-lib/foo? :a) ; valid use
  (foo-lib/foo? :b) ; valid use
  (foo-lib/foo? :c) ; invalid use
  @(rf/subscribe [:foo-lib-foo? :a]) ; valid use
  @(rf/subscribe [:foo-lib-foo? :b]) ; valid use
  @(rf/subscribe [:foo-lib-foo? :c]) ; invalid use
  )
In ”prose” the challenge is something like so: • We have a library that is initialized with a list of things. • It is an error to call some of the library's functions passing things not present in the initialization list. • Some usages of the library goes via re-frame subscriptions, some are ”regular” function calls. • The library is only initialized once during the application life cycle. • The codebase using the library is shared between several apps. I imagine that we'll have at least one linter per app we build, and that we would be hardcoding the initialization list in the linter. Please let me know if I can clarify something, it was surprisingly hard to describe this.
#2022-06-2910:39imreHere are the things I’d question about the above if this was in a PR I’m reviewing: • Is it necessary for the library to manage/hold runtime state? I normally like to place the app in charge of that. • It appears you are trying to make a static analyzer check something that is dependent on runtime state. I’m not sure that is fully possible#2022-06-2910:50roman01la@U0ETXRFEW We actually have re-frame subs linter at Pitch and its implementation can be used for this purpose as well 🙂#2022-06-2911:28borkdudeA while ago @U0FR82FU1 also reached out about something similar, but I haven't heard back. So I assume it was covered already, but if not, please let me know#2022-06-2911:33pez@U04V15CAJ I'm pretty sure that @U0FR82FU1 reached out about a different use case, but very cool to find that we have this experience in-house! 😃#2022-06-2911:35borkdudeok, then I will assume that @U0FR82FU1 can help you with the internal linter and if you need anything from clj-kondo, let me know#2022-06-2911:37pezThe reason I wonder if the linter I am describing above is even possible is the dynamic nature of the what our library works on. Maybe it is similar to how re-frame subscriptions are registered, idk. What I mostly want to know now is the feasibility aspect. If it is even worth trying.#2022-06-2920:43Søren SjørupWith clj-kondo v2022.06.22 I’m getting error: Unresolved symbol: parse-long in cljc and cljs files. Is that to be expected or do I need to change a config?#2022-06-2920:45borkdudeThis symbol is only unresolved if you have an older version of clojurescript on your classpath and the classpath is analyzed by clj-kondo#2022-06-2921:00Søren SjørupHmm ok. I’m using nbb for the cljs, not sure where I’ve set a clojurescript on my path. Will look into it, thanks!#2022-06-2921:00borkdude@U021UJJ3CQ6 I can't reproduce this problem here locally. Can you try from the command line?#2022-06-2921:10Søren SjørupYes I see it both in command line and VSCode.#2022-06-2921:13borkdudeIs your nbb project in the same directory as some other project perhaps? What does clojure -Spath display, is cljs in there?#2022-06-2921:14Søren SjørupYes it’s in the same dir, it’s quite a mess I must admit. This is my path. src:/Users/soren/.m2/repository/borkdude/edamame/1.0.0/edamame-1.0.0.jar:/Users/soren/.m2/repository/org/clojure/clojure/1.11.1/clojure-1.11.1.jar:/Users/soren/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar:/Users/soren/.m2/repository/org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar:/Users/soren/.m2/repository/org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar#2022-06-2921:15borkdudeNo worries. But no CLJS it seems in there right?#2022-06-2921:16borkdudeYou could try to delete .clj-kondo/.cache and restart your editor / reload workspace#2022-06-2921:17borkdudePerhaps some older stale cache#2022-06-2921:18Søren SjørupThat worked! 🙂#2022-06-2921:18Søren SjørupThanks!#2022-06-3011:40pedrorgirardi@borkdude, it seems there’s something in the “EDN analysis” process that is writing to stdout. I experimented with adding deps.edn analysis to my Sublime Text plugin and noticed that the JSON parser was failing in some cases - since there was something else getting printed to stdout that didn’t look like a JSON encoded string.#2022-06-3011:40pedrorgirardi#2022-06-3011:41pedrorgirardiNotice the :git-url nil\ string before the analysis data.#2022-06-3011:42borkdudeHmm, yes, seems to happen here: https://github.com/clj-kondo/clj-kondo/blob/ab3172541dd07e52486962c762c6bd739ab25a09/src/clj_kondo/impl/linters/deps_edn.clj#L126#2022-06-3011:43borkdudeWe should remove this and replace with nil or so#2022-06-3011:43pedrorgirardiThat was fast! 😃#2022-06-3011:44pedrorgirardi> We should remove this and replace with nil or so Cool! Thanks 🙏#2022-06-3011:44borkdudeissue + PR welcome. maybe as a workaround you can do a str/replace on this before you read it as json#2022-06-3011:44pedrorgirardiYep, good idea.#2022-06-3014:52borkdudePhotos from the clj-kondo workshop at ClojureD :) (and other conf pics!) https://twitter.com/borkdude/status/1542521071588347905#2022-06-3015:26Noah Bogart@U0156R9BWGK is that you on the right?#2022-07-0108:29iarenazaIt was real fun, and I learned a ton of new things! So many, many thanks @borkdude#2022-07-0108:30borkdude@U8T05KBEW Thank you!#2022-07-0114:39Hans Conradha @UEENNMX0T that would indeed be me...Not sure why I always look so serious when I see clj-kondo magic.. Thanks again for that session @borkdude definitely learned a lot#2022-07-0110:54SakibI'm getting this error. I'm using vscode Unresolved namespace System. Are you missing a require?clj-kondo(unresolved-namespace)#2022-07-0111:08borkdude@nsakib.cse Need more info please. Your code and file extension. I.e. a repro.#2022-07-0116:10Sakibhttps://github.com/starain31/hello-deps-edn I try to create a sample. Here I got the error in .cljc file but not in .clj file. I don't know the difference of those file type. @borkdude#2022-07-0116:12borkdude@nsakib.cse This is expected since .cljc files are usually used for both Clojure and ClojureScript and System is not a known thing in ClojureScript. You can solve this by writing:
#?(:clj (System/...))
#2022-07-0116:30SakibGot it, thanks. BTW can you recommend some tutorial on Reader Conditionals @borkdude?#2022-07-0116:34borkdudehttps://clojure.org/guides/reader_conditionals#2022-07-0721:02SakibIf I solve by this way
(defn exit
  [status]
  #?(:clj (System/exit status)))
I get another warning unused binding status clj-kondo(unused-binding) I could get away from all warning by adding reader conditionals to the defn
#?(:clj (defn exit
          "Exit the process with `status` and show `msg`."
          [status]
          (System/exit status)))
I'm calling this function from a babashka task
{:paths ["script"]
 :min-bb-version "0.7.0"
 :tasks
 {pre-push {:extra-paths ["test"]
            :requires    ([pre-push])
            :task        (pre-push/main *command-line-args*)}}}
Which technique is correct or preferable?
#2022-07-0721:05borkdude@nsakib.cse Good. Yes, sometimes this can be a bit annoying, but sometimes it can also be helpful to see that you forgot to use a binding in one branch#2022-07-0721:09borkdudeYes, this seems good. bb tasks also supports a short-hand for
:requires    ([pre-push])
:task        (pre-push/main *command-line-args*)}
Simply:
:task pre-push/main
#2022-07-0721:13SakibDo you prefer wrap defn with #?(:clj) ?#2022-07-0721:14borkdudeIf you don't use that function in ClojureScript, why not?#2022-07-0721:14borkdudewhatever works best for you#2022-07-0414:28Stefan@borkdude I assume correct+file.clj is a valid Clojure filename, right? Because I just noticed that the namespace-name-mismatch linter behaves incorrectly on that file name. Before I look into it, I just wanted to confirm that it is indeed a valid file name.#2022-07-0414:30borkdudeDepends on the OS maybe? I would have to look into the correctness as much as you would, using google + macOS + Windows + linux#2022-07-0414:30borkdudeAlso check if clojure itself accepts this#2022-07-0414:31StefanOk, I’ve put it on my list.#2022-07-0415:32Alex Miller (Clojure team)it's a valid namespace name#2022-07-0415:33StefanThanks @U064X3EF3; do you maybe also know whether it is a valid filename on all supported platforms?#2022-07-0415:33Alex Miller (Clojure team)whether it's a valid file name is probably os-dependent#2022-07-0415:33Alex Miller (Clojure team)don't know#2022-07-0415:34StefanOh haha that was quick thanks 🙂#2022-07-0415:38borkdudeSo the issue is probably that we are calling munge on the ns name while we should call demunge on the filename.
user=> (clojure.lang.Compiler/demunge "foo+bar")
"foo+bar"
user=> (munge "foo+bar")
"foo_PLUS_bar"
(and here is me asking is demunge can be become public again :) https://ask.clojure.org/index.php/11371/consider-adding-demunge-into-clojure-core?show=11371#q11371
#2022-07-0415:55Alex Miller (Clojure team)https://clojure.github.io/clojure/clojure.main-api.html#clojure.main/demunge#2022-07-0415:57borkdudeYes, that is mentioned in the ask issue. clojure.main isn't a cross-platform namespace, so putting it there would not make demunge calls "cross platform". Adding it to core would.#2022-07-0416:07Alex Miller (Clojure team)I added this to our 1.12 consideration list#2022-07-0517:01Cora (she/her)is it intended that we should commit (to our code repos) everything that appears under the .clj-kondo directory?#2022-07-0517:08borkdude@corasaurus-hex That's what I do personally, yes. So everyone who checks out the repo has the same linting.#2022-07-0517:16DerekNot the .cache right?#2022-07-0517:17Cora (she/her)that's where I landed, too#2022-07-0517:19dpsuttonHere are the two strategies we have at work:
.lsp/*
!.lsp/config.edn
.clj-kondo/.cache
I think they are basically equivalent now. We specifically ignore the clj-kondo cache. For lsp we ignore everything and then specifically override to track the lsp config
#2022-07-0517:28borkdudeFor both clj-kondo and lsp you can do:
.cache
#2022-07-0517:29borkdudeSo just a single entry for both#2022-07-0613:36souenzzoI'm coding in java and it have a cool code inspection: if I do var x = new Thing() and Thing implements AutoClosable, it warns me about this. Could be nice to have this kind of inspection in kondo, and maybe a code transformation from let to with-open#2022-07-0613:38borkdudeWe don't need a code-transformation for changing 5 characters I think :) Also, warning on this can be nice but I'm sure one can come up with counter-examples where the warning will be a false positive#2022-07-0613:39emccuegood example is a Scanner - you can close it but you made it from http://System.in you're gonna have a bad time#2022-07-0817:59Noah BogartI just ran into a bug where I had (:require [example.company.common :as ecc]) and then later wrote :ecc/some-keyword, and was getting an error because I only used a single colon and the keyword didn't autoresolve to the right namespace. Would you be interested in a linter that checks qualified keywords that share a namespace with an existing namespace alias but aren't auto-resolving?#2022-07-0819:43imreThis is an interesting one. Using it like you wrote is perfectly valid but it can help find these typos. Would keep it at warning level for sure. And it should not only cover keywords but symbols and destructuring as well IMO#2022-07-0819:44Noah Bogartare there auto-resolving symbols?#2022-07-0819:45imreI guess only in ::keys vs :keys destructuring but I might be wrong#2022-07-0916:23borkdudeI haven't made many mistakes that I can remember with this I actually saw a counter-example today:
(require '[sci.core :as sci])
:sci/error 
A bit on the fence about this one, but let's see how others feel about it.
#2022-07-0919:16Noah Bogartyeah, i suspected this wouldn't be a sure-fire lint lol#2022-07-0919:16Noah BogartIf included, I would want it off by default#2022-07-0820:44Stefan TIf you want to configure a :lint-as for a macro in a single namespace, is the best option using namespace metadata? Is there any way to avoid using the fully qualified symbol?
{:clj-kondo/config '{:lint-as {shared-lib.asset-caching-test/with-test-file clj-kondo.lint-as/def-catch-all}}}
#2022-07-0820:45borkdudeNot sure why you would like to avoid a fully qualified symbol?#2022-07-0820:46borkdudeMetadata is one possibility. Another one is using :config-in-ns#2022-07-0820:47Stefan TTo clarify, it’s a macro defined in the same namespace
(ns shared-lib.asset-caching-test
  {:clj-kondo/config '{:lint-as {shared-lib.asset-caching-test/with-test-file clj-kondo.lint-as/def-catch-all}}}}
it’s pretty minor, just wondering if there was a way since it seems like it’s possible with other config options like :exclude
#2022-07-0820:47borkdudeIt's not possible to avoid the fqs#2022-07-0821:27Stefan TIs it possible to disable type-mismatch in the body of a macro? For example: (korma.core/where (< :start_date start-date)#2022-07-0821:31borkdudeCurrently not, but a #_:clj-kondo/ignore before the form should work. A hook would be a better solution here probably#2022-07-0821:31borkdudeoh wait, yes, it is possible#2022-07-0821:32borkdude
:config-in-call {korma.core/where {:linters {:type-mismatch ...}}
#2022-07-0821:34Stefan TNice! That worked. I wasn’t aware of :config-in-call and I don’t see it documented in the config README, is this new?#2022-07-0821:34borkdudeWe should document that. If you can post an issue and/or a PR, that would be helpful#2022-07-0821:34borkdudeit is new#2022-07-0821:35Stefan TVery useful, thanks!#2022-07-0821:35Stefan TI can post a quick issue but I don’t know enough about the feature to PR something#2022-07-0821:35borkdudesure, quick issue is fine#2022-07-0821:36borkdudethe korma example is very useful, please also include that in the issue#2022-07-0821:38Stefan TCool, creating a ticket now#2022-07-0821:39Stefan TStill getting a hang of the configuration. Currently using
:config-in-call {korma.core/where {:linters {:type-mismatch {:level :off}}}}
I’m curious if there’s a way to be more specific to functions like <?
#2022-07-0821:40borkdudelike a CSS selector but for nested calls?#2022-07-0821:41borkdudeI think you can even teach clj-kondo to override the type checking for <#2022-07-0821:41borkdudesee the type mismatch docs#2022-07-0821:41Stefan TI meant is there a way to only disable :type-mismatch for < instead of for everything (in the context of the korma.core/where call)#2022-07-0821:43Stefan TI’m perfectly happy with using {:level :off} and I see the “types” config is still WIP so I think I’ll leave it.#2022-07-0821:45borkdudeyeah, I also tested this but it doesn't work on this granular level yet#2022-07-0821:46borkdudeI think in this case, writing a hook for some of those korma macros would be the best solution#2022-07-0821:46borkdudewhich is more work, but it can be shared with all korma users#2022-07-0821:47Stefan TYeah. If that was to happen would it make most sense to PR that into clj-kondo/config?#2022-07-0821:51borkdudeThat would be a good place#2022-07-0821:51borkdudeor the korma lib itself#2022-07-0821:52Stefan T> or the korma lib itself all cobwebs over there 🙂#2022-07-0823:29Stefan TMaybe I overlooked something, when using the CLI is it possible to only emit errors and hide warnings?#2022-07-0906:24borkdudeYou can set the fail level but it still will output everything. You can use grep to see only errors#2022-07-1103:41Noah Bogartthis is slightly off-topic, lol, but to share my pain, i wrote :macroexpand functions that changed parallel linting my project from 6 seconds to 30.5 seconds. verysweat_g#2022-07-1106:50borkdudeHmm, large and often used macro? Two ways to speed it up: avoid the backtick if you can or use the analyze call hook#2022-07-1106:50borkdudeJust reducing the amount of code generated will help#2022-07-1106:51borkdudeAnd how big is this project? LOC?#2022-07-1118:37Noah Bogart50k lines in src. 3 separate macros that do code walking to define stuff in let blocks, lol. they're used roughly 8k times in the app. i originally just had :unresolved-symbol {:exclude [(game.macros/req [state side eid ...])]}, and that worked, but i wondered if I could use :macroexpand. turns out, I can! but it's slow and doesn't actually make the linting any better#2022-07-1118:42borkdudehaha alright then#2022-07-1118:42borkdudeomg, macros of 50k lines?#2022-07-1118:46Noah Bogartthe base macro is req does some codewalking to see which variables it needs to define and then returns an anonymous function with those variables in a let block:
(defmacro req [& expr]
  (let [needed-locals (find-undefined-locals expr)
        nls (emit-only needed-locals)]
    `(fn ~['state 'side 'eid 'card 'targets]
       (let [
it's used in a collectible card game to define the abilities and effects a given card can do: {:label "do 1 net damage" :effect (req (damage state side eid :net 1))} etc. the high usage count comes from the complex abilities that nest them: (req (do stuff) (continue-ability ... {:effect (req .... {:effect (req ... lol
#2022-07-1118:47borkdudeok - but to summarize, nothing too unexpected I guess#2022-07-1118:48Noah Bogartyeah, no, there's nothing that clj-kondo needs to change, lol, i was just posting the linting difference cuz it's fun and ridiculous#2022-07-1214:13sheluchinI'd like to store the analysis data in a sql db. Is this already being done somewhere? I'd like to use a standard/common schema for it, if there is one.#2022-07-1215:15borkdudeThere is no sql stuff yet. I'm playing around with some SQL stuff where you can store analysis of multiple projects, but there's nothing finished about it. If you've got something useful to share at some point, please do :)#2022-07-1217:16sheluchinThanks @U04V15CAJ, will do :)#2022-07-1216:33MaxI recently wrote this macro:
(defmacro when->
  "If bool is true, return (-> x form). Otherwise, return x unchanged.
   Useful in threading, e.g. (-> {:a 1} (when-> something (assoc :b 2)))"
  [x bool form]
  `(if ~bool
     (-> ~x ~form)
     ~x))
When I try to use it though, clj-kondo complains. For example:
(-> m
    (when-> (some-test (:k1 m)) (assoc :k2 5)))
;; clojure.core/assoc is called with 2 args but expects 3 or more - clj-kondo (invalid-arity)
How do I get clj-kondo to stop complaining?
#2022-07-1216:34borkdudeAre you familiar with lint-as?#2022-07-1216:35MaxA little, what would I lint when-> as though? It takes different args from ->#2022-07-1216:38borkdudeAh right. For this case the :macroexpand hook maybe be best. https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand https://github.com/clj-kondo/hooks-workshop-clojured-2022/blob/main/part-2/README.md#2022-07-1216:39borkdudeYou can basically copy / paste your macro in the config. If you have loss of too many locations, then the :analyze-call hooks is the best option (which isn't too hard for this macro)#2022-07-1216:40Cora (she/her)definitely what @U04V15CAJ said 😅#2022-07-1217:00MaxIs there a way to do it inline, like with metadata or a comment? This is a huge monolith so it feels a little icky to change the entire thing's kondo file for my one local helper macro#2022-07-1217:11Joshua SuskaloPotentially you could lint it as as-> if it isn't too strict about the argument being a symbol#2022-07-1217:39borkdude> Is there a way to do it inline, like with metadata or a comment? No. But perhaps if it's only used very locally, then you can just suppress the linting in it#2022-07-1217:40Joshua Suskalono ns-local config to add the lint-as?#2022-07-1217:46borkdudefor lint-as yes, but not for the hook#2022-07-1217:47Joshua Suskalofair#2022-07-1217:56MaxTIL about #_{:clj-kondo/ignore [:invalid-arity]}, thanks!#2022-07-1219:16ingesolI think cond-> would give you the same as your when->#2022-07-1218:54sheluchinIs there a way to get function call argument information? The way I can think of is to look up the var usage in var definitions and try to match the arity count in case of a variadic, then check the definition's :arglists.#2022-07-1219:56Joshua SuskaloWhat's the actual data you're trying to get? Which arity is being invoked by any given invocation of the function?#2022-07-1220:04sheluchinI'd like to be able to get the argument names being used in a function call.#2022-07-1220:10Joshua SuskaloThen yes, you should be able to look at the arglists metadata from kondo's analysis, but I do want to ask @U04V15CAJ if arglist metadata is automatically populated in analysis. I expect not, in which case you'll have to look at the different arity's argument vectors manually if arglists is not provided.#2022-07-1220:25borkdudearglists is provided but optional data. See https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#extra-analysis#2022-07-1220:39sheluchinYes, saw that part. In my case I'm looking for the arglists on function invocations, not just definitions. I'll make the connections manually if there isn't some convenience flag or function for it.#2022-07-1220:40borkdudeAh right, you want the join on the definition#2022-07-1220:41borkdudeYeah, right now some things are "joined" automatically, like arity info#2022-07-1220:41borkdudeBut not all of it, to save some data size#2022-07-1220:43sheluchinYep, join on definition sounds like what I'm after. So in some cases it is already joined? Could you please mpoint me to the function which does the joining so I can get the full list in case of omissions?#2022-07-1221:01borkdudehttps://github.com/clj-kondo/clj-kondo/blob/09cf8b0fefe3141127f6c0aa7fceabe369707c88/src/clj_kondo/impl/analysis.clj#L27#2022-07-1222:28sheluchin@U04V15CAJ thanks very much.#2022-07-1315:34practicalli-johnWhat arguments do I need to use with clj-kondo to lint a project deps.edn , resources/config.edn , clojure .clj files under src and test directory trees, but not the file .cljstyle in the root directory of the project. I’ve looked at include exclude, but getting only a sub-set of the files linted Do I need to run separate clj-kondo --lint files for each? So 4 different clj-kondo commands?#2022-07-1315:36borkdude@U05254DQM You can probably just do clj-kondo --lint . right? Files that don't end with .clj etc are skipped#2022-07-1315:36borkdudeYou can also do:
clj-kondo --lint deps.edn resources/config.edn src test
#2022-07-1315:38practicalli-johnah, so I can just chain the paths with --lint, that sounds good…#2022-07-1315:38practicalli-johnIs there an option to list what files are being checked#2022-07-1315:39borkdudenot really no, but you could also make an explicit list and then use xargs I guess#2022-07-1315:42practicalli-johnYes, the command line works, thanks. I was getting tripped up with a GitHub action that sets a *.clj* pattern for clj-kondo by default. Hopefully I can over-ride this in the GitHub action and simulate the command line correctly#2022-07-1317:44practicalli-johnIn the end I’ve switched to the clojure-setup GitHub action and used the following command to avoid linting the clojure files under dev directory
clj-kondo --lint deps.edn resources/config.edn src test --config .clj-kondo/config-ci.edn
Works very nicely, thank you.
#2022-07-1407:37grahamcarlyleWhen using clj-kondo via a deps alias it would be nice if clj-kondo would pick up on the paths specified in other aliases for linting rather than having to specify them via the --lint parameter. A common case for me is a test alias which defines the test srcs in :extra-paths , which I have to duplicate in the --lint parameter for clj-kondo invocation. Am i missing a way of currently doing this?#2022-07-1407:40borkdudeclj-kondo does not automatically pick up directories to lint from deps.edn or project.clj#2022-07-1407:45grahamcarlyleIs this worth adding as an issue? This existing issue seems related https://github.com/clj-kondo/clj-kondo/issues/1341#2022-07-1407:46borkdudeI'm not planning to support this, it would introduce magic I'd like to avoid#2022-07-1407:48grahamcarlyleBy magic are you thinking as something not obvious to the user or for the way this would be implemented #2022-07-1407:49borkdudeIt's better to be explicit in what you want to lint, imo.#2022-07-1513:08borkdudeHere's an idea for those who care about arity error linting for reagent components: https://github.com/clj-kondo/clj-kondo/issues/1751#issuecomment-1184759506#2022-07-1513:09borkdudeThe idea is a bit inspired by @U0FR82FU1 's#uix#2022-07-1519:56ericdalloLinter suggestion: warn when a namespace use _ instead of - like (ns foo_bar) instead of (ns foo-bar)#2022-07-1520:01borkdudeYes, issue welcome!#2022-07-1520:05ericdallothanks! https://github.com/clj-kondo/clj-kondo/issues/1753#2022-07-2111:14sheluchinI wonder if it would be possible to have a linter for this guideline: > Only use pure functions with the lazy sequence operations like map, filter, take-while, etc. When you need side effects, use one of these alternatives: https://stuartsierra.com/2015/08/25/clojure-donts-lazy-effects#2022-07-2111:16borkdudeI think we could, certainly if you use a side-effecting clojure var directly in map, etc. With composite functions, we need to introduce some side-effect tracking stuff#2022-07-2111:20sheluchinIt seems to me like it would be helpful. Reasoning about how lazy sequence operations get evaluated can get confusing at times, but with this guideline it's pretty clear how to avoid most of the trouble.#2022-07-2513:14sheluchinI created https://github.com/clj-kondo/clj-kondo/issues/1757 in case there is more interest in this idea.#2022-07-2513:34borkdudeThanks!#2022-07-2322:03Joshua Suskalo@borkdude looks like the unused import linter currently doesn't understand usages of the class in the :gen-class ns clause#2022-07-2322:04borkdudecan you post an example?#2022-07-2322:05Joshua Suskalo
(ns <redacted>
  (:import
   (com.mongodb.kafka.connect.sink MongoSinkTopicConfig)
   (com.mongodb.kafka.connect.sink.processor PostProcessor))
  (:gen-class
   :name "<redacted>"
   :extends PostProcessor
   :constructors {[MongoSinkTopicConfig] [MongoSinkTopicConfig]}))
#2022-07-2322:07Joshua SuskaloThis is what I'm currently working on where I spotted it#2022-07-2322:08borkdudeok, so you're importing it to use it within gen class?#2022-07-2322:09borkdudeissue welcome#2022-07-2322:09borkdudeif you can, make a repro with a standard JDK class which I can run locally#2022-07-2322:09Joshua SuskaloOkay, cool#2022-07-2519:17Joshua SuskaloOkay, turns out this should be an error.#2022-07-2519:17borkdude😅#2022-07-2519:17Joshua SuskaloBecause apparently the classes in your import clause aren't available in the gen-class form#2022-07-2519:17Joshua Suskaloso you need to fully-qualify them.#2022-07-2519:17borkdudeI guess it matters in which order you put those clauses#2022-07-2519:18Joshua SuskaloNope, I have the order in a way that should make sense, but it still resolves non-qualified class names as being from java.lang#2022-07-2519:18borkdudeok#2022-07-2811:54Yehonathan SharvitHow do I disable the linter completely for a specific namespace?#2022-07-2811:55borkdude@viebel Either in the namespace metadata:
(ns foo {:clj-kondo/config '{:linters {foo {:level :off}}}})
or in .clj-kondo/config.edn:
{:config-in-ns {my.namespace {:linters ...}}}
#2022-07-2811:56Yehonathan SharvitThat’s for a specific linter. I want to disable all the linters#2022-07-2811:57borkdudeDoes this work?
{:config-in-ns {my.namespace ^:replace {:linters ...}}}
#2022-07-2811:59Yehonathan SharvitWhat should be instead of ?#2022-07-2812:00borkdudeNever mind, that doesn't work#2022-07-2812:01Yehonathan SharvitAh#2022-07-2812:01Yehonathan SharvitIs there another option?#2022-07-2812:01borkdudeYes, you can do:
{:output {:exclude-files ["foo"]}}
#2022-07-2812:01borkdudefoo is a regex pattern#2022-07-2812:05Yehonathan SharvitWorks!#2022-07-2818:13sheluchinWhat can I use to convert an argist-str->arity? So "[a b]" => 2.#2022-07-2818:23borkdudeWe don't have anything in the API for this. So perhaps edn/read-string + surrounded with try/catch and count the args until & to get the fixed args#2022-07-2818:23borkdudeWhat are you doing with this data?#2022-07-2818:25sheluchinI'm back to looking at this https://clojurians.slack.com/archives/CHY97NXE2/p1657652041362049 and ultimately trying to join the corresponding :var-definition's :arglist-str to a :var-usage.#2022-07-2818:26sheluchinMaybe rewrite-clj's node API would be better than edn/read-string?#2022-07-2818:33borkdudePerhaps. I am using edn/read-string in quickdoc#2022-07-2818:47sheluchinI see. Here it is for https://github.com/borkdude/quickdoc/blob/a8068f1c8b13e09a2966804213fc41dd813de18e/src/quickdoc/impl.clj#L57. I'm looking at this stuff as part of my effort to make a normalized schema of the analysis data. I've decided to scale it back for now and only include functions and their calls (not all vars). I have function arities as separate records referencing their functions. So var-usages -> specific function arities -> fn definitions.#2022-07-2818:49borkduderight#2022-07-2818:51sheluchinThanks for the pointer.#2022-07-2919:13rayatHi! Custom hooks question > (I'm like addicted to these now lol) Haven't seen anything in the docs about this, but is there some kind of support for "multiple" hooks per function? Specifically, I'm thinking of the following: 1. I, with @borkdude’s help of course, introduced a couple hooks for #helix (`defnc/$/d/*`), that have since been released and thus introduced into our work codebase (as we use helix) 2. At the same time, we have some business-logic / org-specific things we want to lint for those same functions, that wouldn't make sense for upstream contribution a. (eg a linter warning against using a business-logic-specific fn that doesn't work well in helix components but works great otherwise) 3. I could turn off clojure-lsp's auto copying of library hooks, and then introduce the desired new org-specific linters inline into our own hook(s) for helix, but then I'd lose automatically getting any upstream changes when helix (and its hooks) update (at which point clojure-lsp would copy over the changed hooks) Any thoughts or prior art on this? 1. I'm wondering, if it doesn't already exist, if some way to override or "cascade" (in the sense of like, CSS or something) hooks might work. ◦ Not sure how one might navigate the fact that the "order" of apply hooks matters a lot, as one hook's output might utterly invalidate subsequent ones' input expectations. 2. Or is it just worth it instead to introduce some degree of configurability into the #helix hooks such that they can - to start with - accept some collection of no-no symbols to warn against usage?#2022-07-2920:04borkdude@rayatrahman9 Currently there can be only one hook for a function/macro. I'm considering multiple hooks, but if one hook transforms the call, then the other hooks won't get to see the input at all, so it's tricky. You could just configure your own hooks, then the imported hooks should be ignored#2022-07-2921:21rayat1. Yeah, tricky indeed. I'll simply say then that I'm very curious what you, in particular, are able to come up with for multiple hooks, should you choose to continue to consider it at all 2. Will try. It will mean still that upstream changes will not be auto copied, but since the upstream library's author is my manager anyways, I don't think it'll be too hard to keep track haha #2022-07-2921:23borkdudeWhat I mean with using it as a library: you could define your own hook, do your own things - don't know if you're only doing some linting or also transformation#2022-07-2921:23borkdudeBut if you don't do transformation, you can then pass the node to the imported hook function#2022-07-2921:28rayatAh yes, missed the import suggestion, very cool! That might be a "decent" first step in "multiple" hooks. ie, pre or post hooks with heavy warnings/caveat/"proceed at your own risk" if they transform (too much, or at all), vs just linting with them.#2022-07-2921:29borkdudeThis is something you can do today, it doesn't need any changes#2022-07-2920:05borkdudePotentially your own hooks could call the imported hooks as a library#2022-07-3012:27sheluchin
clojure.core/defn-
  [name & decls]
  same as defn, yielding non-public def
Why does :varargs-min-arity differ for defn- in the usage and definition analysis?
#2022-07-3012:28sheluchin
;; definition
{:ns clojure.core
 :name defn-
 :doc "same as defn, yielding non-public def"
 :varargs-min-arity 1
 :arglist-strs ["[name & decls]"]}

;; usage
{:name defn-,
 :filename "/tmp/foo.clj",
 :from foo,
 :macro true,
 :col 2,
 :arity 3,
 :varargs-min-arity 2,
 :row 8,
 :to clojure.core}
#2022-07-3012:29borkdudeThat's weird, but perhaps you can figure it out on kondo's source and report an issue about it?#2022-07-3012:30sheluchinYes, I can take a stab at that. I thought perhaps it's the correct result and I just misunderstood something, but if you concur that it's unusual, I'll take a look at the source and put some details in an issue.#2022-07-3013:19sheluchinI think I understand the cause. It looks like overrides are not being applied to definitions, so the expected :varargs-min-arity 1 is reported for [name & decls], but for usages the overrides set :varargs-min-arity 2 https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/overrides.clj#L22-L25#2022-07-3013:24borkdudenice!#2022-07-3016:28sheluchinTried to fix it but couldn't get to the bottom of it. I left some details https://github.com/clj-kondo/clj-kondo/issues/1758. Thanks! 🙏#2022-07-3103:32pinkfrogFor some reason (potemkin is not supported on bb), I am directly using potemkin.namespace, How can I instruct clj-kondo to treat potemkin.namspaces/import-vars as if using potemkin/import-vars ?#2022-07-3113:19roltwith :lint-as probably#2022-08-0106:43Matthew Davidson (kingmob)Heh, funnily enough, I was adding this to Potemkin this weekend#2022-08-0108:08pinkfrog@U10EC98F5 Adding this? I am writing a lib, so I don’t wanna the user to tweak with :lint-as.#2022-08-0111:45Matthew Davidson (kingmob)If you come up with some good hooks, please share? :lint-as worked for many, but I still need to straighten out how import-vars works when I get back to it. #2022-08-0115:05pinkfrog@U04V15CAJ Do you have any thoughts on how to achieving lint-as with import-vars from a lib ?#2022-08-0115:26borkdude@UGC0NEP4Y clj-kondo should just add support for the multi segment potemkin namespace. @U10EC98F5 what is the final name going to be?#2022-08-0205:36pinkfrog@U04V15CAJ Looking at the docs, https://cljdoc.org/d/clj-kondo/clj-kondo/2022.06.22/doc/configuration#exporting-and-importing-configuration, it seems it is impossible to automatically enable the lint-as configuration . The user must activate that on its own.#2022-08-0208:42borkdudeimported configs are now automatically activated, if you stick to the suggested format#2022-08-0215:59Matthew Davidson (kingmob)I wasn't planning to change the Potemkin namespaces unless necessary. Barring some Graal user complaining, that's unlikely#2022-08-0216:01borkdude@U10EC98F5 Then I misunderstood.
Heh, funnily enough, I was adding this to Potemkin this weekend
I thought you were referring to the ns rename recently with some other lib. I'm mixing things up ;)
#2022-08-0216:01borkdudeperhaps potemin isn't problematic with graalvm since it runs at compile time#2022-08-0304:45Matthew Davidson (kingmob)> I was adding this to Potemkin this weekend I meant I was adding useful clj-kondo hints 😄#2022-08-0304:46Matthew Davidson (kingmob)On that note, a question: If I use a macro hook to transform import-vars :
(import-vars [ns1 foo bar]
             [ns2 baz qwerty])
which then becomes for kondo something like:
(def foo ns1/foo)
(def bar ns1/bar)
(def baz ns2/baz)
(def qwerty ns2/qwerty)
is that correct for teaching kondo about the defs? It seemed to work, for teaching kondo about names, but not for getting macro arity right for some of the imported macros. In particular, when I stopped, I was having issues with kondo recognizing the 2-arity version of import-fn, even though import-fn had its own hook. Maybe my misunderstanding is in how hooks work; even without using import-vars, my hook still isn’t working for the import-fn macro. The relevant hook code is:
(defn import-macro*
  ([sym]
   `(def ~(-> sym name symbol) ~sym))
  ([sym name]
   `(def ~name ~sym)))

(defmacro import-fn
  ([sym]
   (import-macro* sym))
  ([sym name]
   (import-macro* sym name)))
Any help appreciated!
#2022-08-0309:40borkdude> is that correct for teaching kondo about the defs? Yes - clj-kondo could do a better job seeing the connection between two vars. There is an issue about this#2022-08-0914:42Matthew Davidson (kingmob)Good news! What’s the issue #?#2022-08-0914:43borkdudehttps://github.com/clj-kondo/clj-kondo/issues/412#2022-08-0914:44borkdudeFeel free to upvote with a thumbs up or if you're really keen, you could try to work on. I kinda know what needs to happen, so I could guide you#2022-08-0915:14Matthew Davidson (kingmob)Are there any code/branches I should look at? I’m not sure if/when I’ll get to it, but Potemkin (and proto-Potemkin) fns are all over Zach’s aleph/manifold/etc code, and I’m tired of staring at a sea of linter warnings. 😅 I can’t really use it for all the false positives.#2022-08-0915:15borkdudeHmm, I could maybe help you with that, if you could give me a starting point#2022-08-0915:16borkdude@U10EC98F5 There is a "proxy var" construct in clj-kondo based on what it detects based on the potemkin macro#2022-08-0915:16borkdudeAnd this same mechanism could be used for (def x y)#2022-08-0915:18Matthew Davidson (kingmob)Huh, I hadn’t realized potemkin had special code already#2022-08-0915:18borkdudeyes, there is special code in clj-kondo to support the usage of potemkin#2022-08-0915:18borkdudebut this is based on potemkin/import-vars usage#2022-08-0915:19Matthew Davidson (kingmob)Well, import-vars was my starting point#2022-08-0915:20borkdudeit already has support for that#2022-08-0915:21borkdudeyou need to lint your project sources first though#2022-08-0915:21borkdudebefore it can make the connections#2022-08-0915:21Matthew Davidson (kingmob)But it doesn’t yet support the other issue, right? Understanding the arity of the “imported” vars#2022-08-0915:22borkdudeI think it does#2022-08-0915:22borkdudethere's test cases you could look at#2022-08-0915:24Matthew Davidson (kingmob)Sure, I’m happy to take a look. I just checked, and it definitely doesn’t understand the import-fn macro’s arity, though#2022-08-0915:24borkdudehttps://github.com/clj-kondo/clj-kondo/blob/a550a8279e1bf2134921d5a31b98aa68c60f5a00/test/clj_kondo/main_test.clj#L2429#2022-08-0915:25borkdudeI thought you were referring to the arity of the imported var, not the import-vars macro itself. Perhaps you can just submit a failing test or so, I think we're talking past each other ;)#2022-08-0915:25Matthew Davidson (kingmob)I added (import-fn unify-gensyms uniqlo) at the bottom of potemkin.clj, and I thought it would know that import-fn has a 2-arity version where the second one is a new symbol, and I thought I got the :macroexpand hook for that correct#2022-08-0915:25Matthew Davidson (kingmob)SOrry about that#2022-08-0915:26borkdudeclj-kondo only has support for import-vars - I've never heard of import-fn#2022-08-0915:26Matthew Davidson (kingmob)If you add that snippet, does it complain about uniqlo?#2022-08-0915:26Matthew Davidson (kingmob)Ah, ok#2022-08-0915:26borkdudebut it could be potentially have that if it's a variation, I just don't know that construct#2022-08-0915:27Matthew Davidson (kingmob)I think import-vars is really the important one. It uses import-fn under the hood#2022-08-0915:27Matthew Davidson (kingmob)And hell, some of the potemkin stuff should also be discouraged…#2022-08-0915:28Matthew Davidson (kingmob)import-fn is not important per se, I was just trying to figure out what, or if, I was doing wrong when adding my own hook for it#2022-08-0915:28borkdudemaybe you could have a hook which expands that into import-vars 😆#2022-08-0915:29borkdudeand then it should work#2022-08-0915:29Matthew Davidson (kingmob)and that’s how he froze his computer tonight#2022-08-0915:30Matthew Davidson (kingmob)WOuld it be an infinite loop?#2022-08-0915:31borkdudeno, because clj-kondo handles that code directly, it doesn't expand to import-fn#2022-08-0915:34Matthew Davidson (kingmob)Cool, well, I shouldn’t let the perfect be the enemy of the good. Even linting many of these should clear up a lot of linter warnings, I hope#2022-07-3120:19sheluchinI'm wondering if there is any way to get the arguments list from functions that are defined like this: (def foo (fn [x] ...)). Any suggestions about how the analysis data could be expanded in this way?#2022-07-3120:39borkdudeIn JVM Clojure, you don't get any arglists metadata for that. clj-kondo could do this, but why?#2022-07-3120:54sheluchinI'm presuming the reason that LSP is able to show function arguments for defn functions and not fn functions is because clj-kondo provides more details about the defn. My rationale is that they're both accomplishing the same thing and it would be more consistent for clj-kondo to be able to provide as much of the same data as possible on both forms. But if you don't think it's a reasonable thing I think I can figure out how to do it by using something like clj-kondo.impl.analyzer/analyze-fn-arity. Looks like some of the tests use a fairly small ctx map in places where it's needed.#2022-07-3120:56borkdudeI think we could add this info. But why not just use defn instead?#2022-07-3120:59sheluchinGood question 🙂 I don't know why people opt for the (def (fn approach, but they do. As for myself, I'm hacking away on a Clojure code exploration tool that leverages clj-kondo, so I'm at the mercy of the community.#2022-07-3121:00borkdudeOK, issue welcome. clj-kondo itself tracks arity info for this:
$ clj-kondo --lint - <<< '(def f (fn [])) (f 1 2)'
<stdin>:1:17: error: user/f is called with 2 args but expects 0
so I think it would be a small step to improve this
#2022-07-3121:03sheluchinOkay, thanks very much. I'll create an issue to track this.#2022-08-0111:36sheluchinhttps://github.com/clj-kondo/clj-kondo/issues/1760#2022-08-0315:44NickNameI wonder what might be causing it. I don’t have any other format in the namespace. I also tried to delete .clj-kondo/.cache but the error still persists.#2022-08-0315:46borkdude@islambeg format isn't available in .cljs#2022-08-0315:47NickNameOh didn’t know that, thanks!#2022-08-0315:56borkdude#2022-08-0318:39DumchHey! I am trying to write a little stack based DSL and set up clj-kondo to check the syntax. May be someone did something like this? Two questions. 1. Is it a good idea in general to use clj-kondo for this? 2. I don't know how to parse syntax inside a hook. As I get it, there is no way to use core.spec or instaparse here. And I can't even require a clj-kondo.hooks-api/prewalk (but it seems to be in the https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/hooks_api.clj):
WARNING: error while trying to read hook for dumch.concatenative/defstackfn: prewalk does not exist
#2022-08-0318:40borkdude@arturdumchev In the hook environment you have clojure.walk/prewalk#2022-08-0319:08Stefan TWhen linting a directory, is it possible to globally exclude certain patterns? In my case I'm seeing that kondo spends a lot of time node_modules and some other directories with many files that I'd like to have kondo skip all together.#2022-08-0319:09borkdude@stefan.toubia I recommend not including node_modules in the --lint arguments#2022-08-0319:09borkdudeIf you're doing --lint . then change it into --lint src test whatever#2022-08-0319:10Stefan TIn my case I'd like to lint a directory containing dozens of projects all in one go. This directory contains more than just Clojure projects though.#2022-08-0319:10Stefan TBasically I'm trying to lint the entire monorepo#2022-08-0319:11borkdude@stefan.toubia Maybe a little bit of scripting is more appropriate here then. E.g. recurse through all repos and extract all source dirs or all .clj files and then pass that#2022-08-0319:11borkdudeYou can call clj-kondo from #babashka as well#2022-08-0319:15borkdudeIt's also recommended to call clj-kondo from within each project and not from a global parent directory. You can also do this with scripting#2022-08-0319:15Stefan TYeah OK maybe I'll give that a try, thanks. I agree that exclusion patterns are kind of a pain to deal with. Ignoring node_modules is a regular problem for most tools though (damn you Node!)#2022-08-0319:16borkdudeHaha, Node is the reason I moved all my code out of Dropbox (I used that as an extra safeguard before committing)#2022-08-0319:19Stefan TIs kondo currently able to read deps.edn to find the class paths that should be linted?#2022-08-0319:20borkdude@stefan.toubia No#2022-08-0319:20borkdudeyou can feed clj-kondo a classpath with $(clojure -Spath)
#2022-08-0319:22Stefan TAh of course. Well then I guess I'm already set, our monorepo has an aggregated deps.edn in the repo root with all projects paths listed. Thanks again for your help!#2022-08-0319:23borkdudeNote that this path will also include all dependencies#2022-08-0319:36Stefan TAh yes, this is true. Are there valid use cases for linting dependencies, does kondo need to do this to maybe lint macros from those dependencies? I'm back to wondering if a global exclude makes sense, in my case I could exclude .m2 and node_modules directories.#2022-08-0319:37borkdude@stefan.toubia I recommend reading this: https://github.com/clj-kondo/clj-kondo/#project-setup#2022-08-0319:38borkdudeYou can lint your src folders without linting dependencies first, this works fine, but will give you less accurate analysis#2022-08-0319:39borkdudeE.g. if you're interested in finding that your code calls foo.bar/baz with the wrong amount of arguments, you need to analyze foo.bar first#2022-08-0319:44Stefan TAh ok thanks that makes sense.#2022-08-0401:13bortexzI am trying to make a custom macro to be linted as one in another library, specifically I want a while-let macro in a library to be linted as better-cond.core when-let , I have this on clj-kondo.exports
{:lint-as {bortexz.utils.core/while-let better-cond.core/when-let}}
But can’t make it work, on a third library using bortexz.utils.core , both the exported config.edn ’s appear con .clj-kondo (both better-cond config.edn and utils.core config.edn). When I change to lint as clojure.core/when-let, it works properly and doesn’t complain. Any clue how can I solve this? Thanks!
#2022-08-0408:00bortexzOn the other hand, better-cond’s export seems to work fine#2022-08-0409:17borkdudeThis would work if you also include better-cond in your classpath#2022-08-0409:18borkdudeIf this doesn't work, please create a repro and I'll look into it#2022-08-0409:21bortexzI am requiring better-cond in bortexz.utils.core, and also tried from the library that uses bortexz.utils.core directly instead of transitively, couldn’t make it work (although the better-cond config.edn works fine)#2022-08-0409:21borkduderepro?#2022-08-0409:22bortexzOn it 👍#2022-08-0409:28bortexzhttps://github.com/bortexz/kondo-exports-issue-repro#2022-08-0708:48bortexzHi @U04V15CAJ were you able to have a look at this? Do you want me to open an issue? specifically, in this file https://github.com/bortexz/kondo-exports-issue-repro/blob/main/src/bortexz/kondo_exports_issue_repro.clj for me using Calva it lints the v as being unresolved symbol in while-let, although in .clj-kondo both of these config.edn exist (exported from their own libraries)
;; bortexz.utils.core
{:lint-as
 {bortexz.utils.core/while-let better-cond.core/when-let
  bortexz.utils.core/while-some better-cond.core/when-some}}

;; better-cond.code
{:hooks
 {:analyze-call
  {better-cond.core/cond better-cond.core/cond-hook
   better-cond.core/defnc better-cond.core/defnc-hook
   better-cond.core/defnc- better-cond.core/defnc-hook
   better-cond.core/if-let better-cond.core/if-let-hook
   better-cond.core/if-some better-cond.core/if-let-hook
   better-cond.core/when-let better-cond.core/when-let-hook
   better-cond.core/when-some better-cond.core/when-let-hook}}}
#2022-08-0709:07borkdudeHaven't checked, will look now#2022-08-0709:19borkdudeI can reproduce the issue. clj-kondo issue welcome#2022-08-0709:50bortexzThanks, will open an issue#2022-08-0406:53liborioIn my project, clj-kondo does not seem to detect invalid arity errors on method calls coming from dependencies that are imported with :local/root in my deps.edn. Do I need to specify something in particular to enable it?#2022-08-0409:19borkdudeDependencies are linted when you provide the classpath. See https://github.com/clj-kondo/clj-kondo/#project-setup#2022-08-0409:29liborioThanks for the answer 🙏 This solved my issue#2022-08-0423:46DumchDoes anyone has an example of a project, where the same code is reused between sorce code and clj-kondo hook?#2022-08-0515:29Joshua SuskaloThat's not really something I'd do without just copying the code. I guess you could like symlink a file into the directory and get it with require, but that severely limits what you can do in that utility file.#2022-08-0715:01DumchI end up copying the code 🙂 thanks#2022-08-0608:27pinkfrog#2022-08-0608:42borkdudeYou can verify this yourself in a REPL:
user=> AutoCloseable
Syntax error compiling at (REPL:0:0).
#2022-08-0609:04pinkfrogI have the general impression that all things under java.lang are directly accessible. Why here isn’t the caes?#2022-08-0609:05pinkfrogFor example, Object and Thread from java.lang are directly accessible.#2022-08-0609:07borkdudeThis is not the case for everything#2022-08-0609:32pinkfrogyes. might be class only:#2022-08-0609:32pinkfroghttps://clojure.org/reference/java_interop#2022-08-0609:33borkdudeDon't complain to me, this is just not the case for all classes as you can verify in a REPL. This is not a kondo problem. Take it up with the people who wrote those docs.#2022-08-0609:34borkdude
user=> java.lang.ProcessHandle
java.lang.ProcessHandle
user=> ProcessHandle
Syntax error compiling at (REPL:0:0).
Unable to resolve symbol: ProcessHandle in this context
#2022-08-0609:35borkdudeKondo just tells you what is the case, it's not going to change your Clojure implementation for you :)#2022-08-0609:35pinkfrogNo complain. It just breaks my previous impression with what’s automatically accessible.#2022-08-0609:38borkdudeit's a fixed list which isn't updated#2022-08-0612:36Alex Miller (Clojure team)That auto import list hasn't been updated in a while - we have a ticket for it. #2022-08-0612:37Alex Miller (Clojure team)They've added so much stuff, I'm not sure that we will want to add everything when we do update it#2022-08-0613:21borkdudeI'd be fine with not adding anything to that and being explicit about imports#2022-08-0613:25Alex Miller (Clojure team)Yeah, it needs some analysis, just haven't gotten around to doing it#2022-08-0613:26borkdudeI wonder if there are potential breakages if someone has already imported foo.bar.ProcessHandle and then adding java.lang.ProcessHandle as an auto-import#2022-08-0613:27Alex Miller (Clojure team)Yeah, stuff like that is something I worry about #2022-08-0613:27Alex Miller (Clojure team)Same kind of problem as adding new stuff to core with auto refers#2022-08-0704:01vemvMight be a FAQ so I figured I'd ask here. How come the :consistent-alias linter needs a pre-configured corpus? Have you considered that in a given project, if I use a :as b and a :as c that is clearly inconsistent and would not need a config?#2022-08-0704:02vemvFWIW I have a custom linter for this sort of thing, but where I can I try to get people to use clj-kondo first :)#2022-08-0706:28borkdudeThis has come up before. You can find the reasoning in the original issue on GitHub #2022-08-0707:06vemvMy understanding is that it boils down to point 4? https://github.com/clj-kondo/clj-kondo/blob/a550a8279e1bf2134921d5a31b98aa68c60f5a00/doc/dev.md#design-principles#2022-08-0707:16borkdudeI'm trying to find the original issue but this is extremely hard...#2022-08-0707:16borkdudeIt was in a discussion with Dave Yarwood I remember#2022-08-0707:18vemvI took the link from https://github.com/clj-kondo/clj-kondo/issues/561#2022-08-0707:19borkdudeok yes, this is the main consideration: https://github.com/clj-kondo/clj-kondo/issues/561#issuecomment-547539721#2022-08-0707:19borkdudethere is a little tool here to populate your config: https://github.com/oxalorg/clj-konmari/#2022-08-0707:23vemv> ok yes, this is the main consideration: If that is the main consideration (and not a higher-level design consideration), I disagree. If you have a linter failure for two aliases, you can, instead of adding config at all, solve the conflict by changing one of the aliases. i.e. the 'endgame' is to have consistent aliases, not to have a config. There's a very objective, desirable advantage to this approach: you get consistency enforced for all aliases - not for a cherry-picked subset. i.e. 100% coverage. Had you considered the matter in this way?#2022-08-0707:29borkdudeI'm afk for a bit, will reply later#2022-08-0709:06borkdudeRight, so, yes with :inconsistent-alias you can specify the namespaces you care about, namespaces not mentioned there aren't considered. This can be considered a feature or a shortcoming. Some people might consider the linter to be too strict if you would consider namespaces not mentioned there, although this could be configured perhaps. To implement the strict mode, clj-kondo would have to keep data in the cache of every namespace + alias encountered, which is not impossible but also not trivial.#2022-08-0709:10vemvThanks for the reponse. Maybe I dont agree with "too strict", it's very annoying to have projects with inconsistent aliases. I'd go as far as saying that it's detrimental for the ability to properly code-review things over github, etc. > To implement the strict mode, clj-kondo would have to keep data in the cache of every namespace + alias encountered, which is not impossible but also not trivial. Maybe this is the sort of thing that clojure-lsp is already good at?#2022-08-0709:10borkdudeThere could be a mode in which you lint multiple namespaces at once in which clj-kondo reports this, so not the editor mode let's say, but a CI mode, then it would be much easier to implement.#2022-08-0709:11borkdudeIt's also not so hard to do this yourself in a :custom-lint-fn over the analysis data#2022-08-0709:11vemv(...Again, I have a linter that addresses this https://github.com/nedap/formatting-stack/blob/main/src/formatting_stack/linters/ns_aliases.clj but I'm mostly interested in something that can reach as many people as possible without convincing them of extra tooling etc)#2022-08-0709:13borkdudeOne other thing to consider is: what should the error message look like: Inconsistent alias found for foo: yes, alright, but what to do now? Scan the project for occurrences of foo: or configure clj-kondo's consistent-alias linter? Well, then we're back at where we are now. All trade-offs considered, I think having a small tool like konmari printing a config for you and regularly updating it, isn't too bad#2022-08-0709:16borkdudeI think the expectation of this linter would be clearer if it were named :preferred-alias , that's really what it is#2022-08-0709:19vemvExample message: The alias foo is inconsistently used in the project. An extended description in the .md could be as verbose as desired. Probably for non-novice Clojure programmers the preferred course of action would be self-evident anyway > I think having a small tool like konmari printing a config for you and regularly updating it, isn't too bad It seems very ugly to have a huge list regularly being spit from a foreign tool. It's just more moving pieces e.g. now I have extra stuff in CI? More security weak spots also > I think the expectation of this linter would be clearer if it were named :preferred-alias I agree with that, but this seems a pretty big opportunity for clj-kondo for making codebases fundamentally better. Which benefits everyone in the community, workplaces etc#2022-08-0709:20borkdudeAlright, issue welcome.#2022-08-0709:21borkdudeIf you can, leave in the "thumbs up" message so we can poll how much the community wants this, so it can be prioritized accordingly.#2022-08-0709:21borkdudeI'm also open to PRs#2022-08-0715:00DumchIs it possible to extend others hooks? For example, I am writing a DSL. I implemented it with protocols, so anyone can get a library and extend it locally. But is there a way for him/her to extend my hook as well?#2022-08-0715:01borkdude@arturdumchev I think so yes#2022-08-0715:04DumchBut how do you extend hooks? What would be the approach? May be there is an example?#2022-08-0715:04borkdudeThrough protocols or multimethods?#2022-08-0715:06DumchSo If I get a library with hook based on protocol, I can add a hook locally with protocol extension, and lib's hook will see it? Great!#2022-08-0715:07borkdudeyes, if you require your protocol#2022-08-0715:12borkdudeNote: only namespaces that are referenced in hooks are loaded and also namespaces required in hook namespaces. So if a user extends your protocol, that extension will only be loaded if the namespace is referenced somewhere#2022-08-0715:29DumchHow to I reference node?
(extend-protocol IExpression
  clj_kondo.impl.rewrite_clj.node.token.TokenNode ...
Could not resolve symbol: clj_kondo.impl.rewrite _clj.node.token.TokenNode I tried require node, but didn't work
(ns hooks.defs
  (:require [clj-kondo.hooks-api
             :refer [token-node list-node vector-node reg-finding!
                     token-node? list-node? vector-node? sexpr]]
            [clj-kondo.impl.rewrite-clj.node :as node]
            [clojure.string :as str]))
getting: error while trying to read hook for dumch.concatenative/defstackfn: Could not find namespace: clj-kondo.impl.rewrite-clj.node.
#2022-08-0715:31borkdudeThis isn't exposed#2022-08-0715:32borkdudeI think you're better off using the :tag of the node and use multimethods#2022-08-0715:43DumchSorry, one more question: what am I doing wrong? I tried to get tags on parent node children: (println head :class (class head) :tag (:tag head)) And I see nils on symbol (TokenNode) tags:
<token: !a> :class clj_kondo.impl.rewrite_clj.node.token.TokenNode :tag nil
<token: !b> :class clj_kondo.impl.rewrite_clj.node.token.TokenNode :tag nil
<list: (invoke> + 2)> :class clj_kondo.impl.rewrite_clj.node.seq.SeqNode :tag :list
#2022-08-0715:44Dumchone way to go with multimethod is to have dispatch function as (-> % class str), but seems not elegant#2022-08-0715:44borkdudeHmm, not sure why the tag is missing. Can you post a issue + repro?#2022-08-0717:23Dumchhttps://github.com/clj-kondo/clj-kondo/issues/1768#2022-08-0907:07jumarI'm noob when it comes to configuring clj-kondo and I'm playing with guardrails: https://github.com/fulcrologic/guardrails#quick-start Emacs complains about <defn macro and its syntax so I'd like to fix it. I noticed guardrails has clj-kondo config: https://github.com/fulcrologic/guardrails/tree/develop/.clj-kondo ... which links to https://github.com/fulcrologic/guardrails/tree/develop/src/clj-kondo/clj-kondo.exports/com.fulcrologic/guardrails How can I make it work when using guardrails as a library?#2022-08-0907:15borkdudeTry this: https://github.com/clj-kondo/clj-kondo#project-setup#2022-08-0907:26jumarHmm, it finishes very quickly giving me this:
clj-kondo --lint "<classpath>" --dependencies --parallel --copy-configs
No configs copied.
#2022-08-0907:26jumarAh, sorry, I didn't read very far...#2022-08-0907:27jumar
clj-kondo --lint $(clojure -Spath) --dependencies --parallel --copy-configs
this looks better
#2022-08-0907:33jumarBut it didn't help much. Do I need to restart emacs once this is done? (I just killed the buffer and opened it again)#2022-08-0907:41borkdudeCan you check what is in your .clj-kondo folder now?#2022-08-0907:44jumarHmm, there's nothing like that in the project root#2022-08-0907:56borkdudeYou first have to create the .clj-kondo directory manually#2022-08-0907:57jumarOuch, why clj-kondo --lint ... doesn't do that automatically?#2022-08-0907:58borkdudebecause else your project would be littered with .clj-kondo directories#2022-08-0907:58borkdude.clj-kondo is used to detect the project root#2022-08-0908:00jumarHmm, I can imagine the use case for it but cannot you just make people run this command in the project root anyway? (Instead of making them to run the command in the project root) Or you have a use case to run it only in subfolder(s)?#2022-08-0908:00borkdudethe clj-kondo binary is also used from emacs and flycheck doesn't execute it from a project root, the cwd is the file you're editing, so unfortunately no#2022-08-0908:02jumarOk, got it. Thanks for the help. I hope I can make it work now 🙂#2022-08-0908:04borkdudekeep me posted ;)#2022-08-0908:08jumarLooks good now, thanks again!#2022-08-0913:51Noah BogartIn a couple places, I have functions like (def get-body (comp :body http/get)). clj-kondo treats these symbols as normal symbols instead of functions. What's the best way to make clj-kondo treat this as the function http/get? (same arg list, etc)#2022-08-0914:05Joshua SuskaloI think you could add it to :lint-as although I'm not entirely sure.#2022-08-0914:05Noah Bogartoh that's a good point#2022-08-0914:06Noah Bogarti wish i could attach :lint-as and other data directly to the var so i didn't have to worry about them getting out of sync because someone forgot lol#2022-08-0914:07Joshua SuskaloYeah, understandable.#2022-08-0914:28borkdudeThe best way would be to write functions using defn and avoid comp :)#2022-08-0914:33Noah Bogarthaha Yeah, I agree, but my boss is... persnickety about some stuff, so I'm hoping to just make my own life a little easier#2022-08-0914:34borkdudehaha, I know, some people go a bit overboard with comp and partial#2022-08-0915:55eval2020It’s the end of the day, I might be totally overseeing something obvious, but I can’t find what’s wrong here:
$ clj-kondo --lint malli_select.clj | grep Unparsable
malli_select.clj:0:0: error: Can't parse malli_select.clj, Unparsable namespace form
~/projects/garden/malli/schema_select (master *)
$ head malli_select.clj
(ns malli-select
  (:require [clojure.test :as test :refer [deftest is testing are]]
            [malli.core :as m]
            [malli.generator :as mg]
            [malli.util :as mu]))
$ clj -M -m malli-select
Works!
Nuking the requires doesn’t fix it. Renaming file and namespace to foo doesn’t fix it…
#2022-08-0915:57borkdude@eval2020 Did you try the smallest repro possible?#2022-08-0915:59eval2020emptying the file and copying the exact ns-form does not yield the error.#2022-08-0916:00borkdudeDo you have more require forms in the namespace?#2022-08-0916:03eval2020Ah, some (require '[]) in a comment-block#2022-08-0916:05eval2020good to know - thanks#2022-08-0916:06borkdudeclj-kondo could do a better job of not crashing on that though. issue welcome#2022-08-0916:07eval2020right - or point to the offending line maybe…#2022-08-0917:14borkdudeyes, that's what it should do#2022-08-0921:20borkdudeposted an issue here: https://github.com/clj-kondo/clj-kondo/issues/1771#2022-08-1009:25hanDerPederHow to I lint a macro like:
(defmacro with-resource [symbol & body])
so it’s like with-open but with a symbol instead of a binding vector. symbol should be used in body
#2022-08-1009:27borkdude@peder.refsnes This macro is similar to cljs.test/async so you could use :lint-as for this#2022-08-1009:32hanDerPederthanks. anyway I could have figured this out myself? My strategy is usually to only look in clojure.core for a similar macro. is this the definition? https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/analyzer/test.clj#L26#2022-08-1009:33borkdudeThe definition is in clojurescript#2022-08-1009:34hanDerPederof the lint rule?#2022-08-1009:34borkdudesyntax looks like this:
(async done ... .... (done))
#2022-08-1009:34hanDerPedermeant the definition of the lint rule, not the macro. my bad#2022-08-1009:34borkdudeJust try :lint-as {your/macro cljs.test/async}#2022-08-1009:35borkdudeclj-kondo knows about the syntax of cljs.test/async#2022-08-1009:35borkdudethis is why :lint-as works#2022-08-1009:36hanDerPederI did, it works. but does not assert the usage of symbol in body. wanted to try creating a rule in clj-kondo that would do that for fun#2022-08-1009:37borkdudeah right.#2022-08-1009:37borkdudeI think you're better off creating your own hook then: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2022-08-1009:37hanDerPederaha, I see. thanks! ❤️#2022-08-1009:39borkdudeIf the docs are too terse, you can consider doing these exercises: https://github.com/clj-kondo/hooks-workshop-clojured-2022#2022-08-1009:40hanDerPedernice, thanks :thumbsup:#2022-08-1011:24hanDerPedergiven this macro
(defmacro with-resource [symbol & body]
  `(let [~symbol (constantly 1)]
     
I want a hook for linting it. Came up with this
(defn with-resource [{:keys [:node]}]
  (let [[sym & body] (rest (:children node))
        fn-node (api/list-node
                 (list (api/token-node 'constantly)
                       (api/token-node 'nil)))

        new-node (api/list-node
                  (list* (api/token-node 'let)
                         (api/vector-node [sym fn-node])
                         body))]
    {:node new-node}))
This works exactly as I want it to. Just wondering if there is a more idiomatic way of writing it.
#2022-08-1100:18jcoyleHi! I would like to lint hiccup that exists within cljs or cljc source code. A contrived example of a linting target would be:
[:div {:id :foo} {:class :bar} "hi"]
The linting logic would surface that there are maps at index 1 and 2 in the hiccup vector, which might be helpful in the case the 2nd map is, in fact, a mistake. Wondering if something (similar) already exist for this? If not, is clj-kondo Hooks the right approach to roll my own solution? If so does anyone know of some examples that might be helpful?
#2022-08-1106:43rolti guess one question is: how can you distinguish hiccup vectors from regular vectors ?#2022-08-1106:44roltzprint has some logic for it for instance, but there are quite a few false positive#2022-08-1109:45borkdudeUnfortunately you can't hook into vectors yet with hooks#2022-08-1215:20Joshua SuskaloHey @borkdude is it in the cards to update the deps.edn linter to understand sourcehut inferred git urls?#2022-08-1215:35borkdude@suskeyhose issue + optionally PR welcome#2022-08-1215:58Joshua SuskaloWorking on the PR at the moment. It looks like there's no tests specifically for checking valid inferred git urls.#2022-08-1216:06borkdudethere is a deps.edn linter test section somewhere I think#2022-08-1216:14Joshua SuskaloYeah, I'm looking at it, but it doesn't explicitly test inferred git urls.#2022-08-1216:14Joshua SuskaloIt does test them implicitly as an aside bit during some tests it seems.#2022-08-1216:14Joshua SuskaloBut there's no explicit tests for inferred git urls.#2022-08-1216:15borkdudeFeel free to add a few#2022-08-1216:16borkdudeMost tests are setup as: throw some code at the linter and test the output#2022-08-1216:16Joshua SuskaloYeah, that's what I'm looking at. Sounds good.#2022-08-1216:17Joshua SuskaloAlso looking at the code for it I get why you did it just as simple prefixes, so you wouldn't need a lot of these updates when new ones are added, but I do note the lint is pretty forgiving about incorrect inferred urls.#2022-08-1216:17Joshua SuskaloMaybe that's fine though since it'd be caught by actually trying to build the project.#2022-08-1216:18borkdudeThere's only 24 hours in a day and so many features to work on :)#2022-08-1216:18borkdudeGlad you're helping out with this PR though#2022-08-1216:18Joshua SuskaloYeah, that's totally fair. And I think this is a fine place to make that compromise.#2022-08-1216:21Joshua SuskaloDoes testing work to do multiple tests with the assert-submaps bit or am I better off making two deftests?#2022-08-1216:23Joshua SuskaloLooks like it should work#2022-08-1218:17Joshua Suskalo@borkdude https://github.com/clj-kondo/clj-kondo/pull/1775#2022-08-1218:18borkdudeLooks good!#2022-08-1218:20Joshua Suskaloawesome, thanks. lmk if I need to make any changes.#2022-08-1218:21borkdudejust waiting for tests to pass, looks good#2022-08-1218:24Joshua Suskaloawesome, thanks!#2022-08-1218:25borkdudeLikewise!#2022-08-1215:43Joshua Suskalocool#2022-08-1216:35DumchDoes anyone use nvim conjure to run clj-kondo with deps? I have problems adding flow-storm debugger. Details in thread. P.S. fixed#2022-08-1217:30DumchI have locally :nrepl alias:
{:aliases 
 {:nrepl
  {:extra-deps 
   {nrepl/nrepl {:mvn/version "0.9.0"}
    refactor-nrepl/refactor-nrepl {:mvn/version "3.5.4"}
    cider/cider-nrepl {:mvn/version "0.28.5"}
    criterium/criterium {:mvn/version "0.4.6"}
    com.clojure-goes-fast/clj-java-decompiler {:mvn/version "0.3.1"}
    com.github.jpmonettas/flow-storm-dbg {:mvn/version "2.3.131"}
    com.github.jpmonettas/flow-storm-inst {:mvn/version "2.3.131"}}
   :main-opts  
   ["-m" "nrepl.cmdline" ;"--port" "14563" 
    "--middleware" 
    "[cider.nrepl/cider-middleware,refactor-nrepl.middleware/wrap-refactor]"]}}
It adds flow-storm-dbg . If I ran a project with: clj -M:test:nrepl My REPL doesn't see flow-storm in classpath (can't require it). But clj -Stree -M:test:nrepl returns a tree, where I can see that flow-storm dependencies. Without test alias: clj -M:nrepl it works (I can require flow-storm): :test is an alias is inside clj-kondo deps.edn
:test
           {:extra-deps
            {org.clojure/clojure {:mvn/version "1.9.0"}
             org.clojure/clojurescript {:mvn/version "1.11.54"} ;; for extraction
             cognitect/test-runner
             {:git/url ""
              :sha "cb96e80f6f3d3b307c59cbeb49bb0dcb3a2a780b"}
             clj-commons/conch {:mvn/version "0.9.2"}
             jonase/eastwood {:mvn/version "1.2.2"}
             borkdude/missing.test.assertions {:mvn/version "0.0.2"}
             babashka/process {:mvn/version "0.1.0"}
             org.clojure/tools.deps.alpha {:mvn/version "0.12.1048"}}
            :extra-paths ["test" "extract"]
            :main-opts ["-m" "cognitect.test-runner"]}
I also found out that it doesn't work with lein if I add flow-storm dependencies inside project.clj (edited)
#2022-08-1219:05Dumch
user=> (require '[flow-storm.api :as fs-api])
FileNotFoundException Could not locate flow_storm/api__init.class or flow_storm/api.clj
 on classpath. Please check that namespaces with dashes use underscores in the Clojure
file name.  clojure.lang.RT.load (RT.java:463)
user=> (require '[portal.api :as p])
CompilerException java.io.FileNotFoundException: Could not locate clojure/datafy__init.
class or clojure/datafy.clj on classpath., compiling:(portal/runtime.cljc:1:1)
I've also tried to add portal, same errors with not being able to find datafu So the problem is that Clojure 1.9 doesn't have datafu (fyi @borkdude, @UEENNMX0T) I will just add 1.11.0 into my :nrepl alias
#2022-08-1219:06borkdudeGood to see it's fixed!#2022-08-1217:09Noah Bogartwhat's your :test alias look like?#2022-08-1217:10Dumch*Put into thread above#2022-08-1217:20borkdude🧵 plz#2022-08-1306:21jumarIs it possible to get var usage form source code out of the box if I have kondo analysis result? I want something like this and I'm wondering if I need to code that manually or if there's a way to get it from kondo analysis by default:
(defn var-usages
  "Finds usages of var with given name defined in given namespace.
  Both `the-ns` and `var-name` should be symbols."
  [kondo-analysis the-ns var-name]
  (->> kondo-analysis
       :var-usages
       (filter #(and (= var-name (:name %))
                     (= the-ns (:to %))))))

(defn add-var-usage-source
  [{:keys [row col end-row end-col filename] :as var-usage}]
  (let [file-source (->> filename slurp str/split-lines)
        matching-rows (subvec file-source (dec row) end-row)
        matching-source (if (= 1 (count matching-rows))
                          (subs (first matching-rows) (dec col) (dec end-col))
                          (str/join
                           [(subs (first matching-rows) (dec col))
                            (subs (last matching-rows) 0 (dec end-col))]))]
    (assoc var-usage :source matching-source)))

(defn var-usages-with-sources [kondo-analysis the-ns var-name]
  (let [all-usages (var-usages kondo-analysis the-ns var-name)]
    (map add-var-usage-source all-usages)))
#2022-08-1307:07borkdudeThis is currently not part of the analysis#2022-08-1416:55jumarGood to know, thanks for the confirmation. Could this be a useful future addition?#2022-08-1417:31borkdudeWe could document this snippet perhaps, as a first step#2022-08-1417:33borkdudeI've added a wiki page here now: https://github.com/clj-kondo/clj-kondo/wiki/Analysis-tips-and-tricks Feel free to put it there#2022-08-1418:23jumarPosted, thanks.#2022-08-1418:24borkdudeThank you!#2022-08-1308:26pinkfrogMaybe more related to the developer of meander, but I wonder why meander does not add this
:linters {:unresolved-symbol {:exclude [(meander.epsilon/match)
                                         (meander.epsilon/find)
                                         (meander.epsilon/search)
                                         (meander.epsilon/rewrite)]}}
to the library by default.
#2022-08-1411:31pinkfrogI did a
:linters
 {:unresolved-symbol {:exclude [(meander.epsilon/match)
                                (meander.epsilon/find)
                                (meander.epsilon/search)
                                (meander.epsilon/rewrite)]}
  :unresolved-var {:exclude [(meander.epsilon/scan)]}}
yet, the m/scan is still unresolved.
#2022-08-1412:19pinkfrogI found this.#2022-08-1612:30teodorluI'm writing a library, and clj-kondo gives me lots of "unused public var" warnings for my public API namespace. I'm curious about how other people who are writing libraries and are using clj-kondo are doing here. Do you simply disable "unused public var" warnings for the whole namespace?#2022-08-1612:30borkdudeunused public var isn't a clj-kondo thing, it's a clojure-lsp thing.#2022-08-1612:31teodorluOh! Thanks. I'll ask in the right channel :thumbsup:#2022-08-1612:31borkdudebut carve has a similar thing where you can say: this is an API namespace, ignore unused vars here#2022-08-1612:31borkdudeI expect that clojure-lsp will have something similar#2022-08-1612:33teodorluYou're referring to the :api-namespaces option? (from https://github.com/borkdude/carve)#2022-08-1612:34borkdudeyep#2022-08-1612:34teodorluThanks!#2022-08-1612:58ericdalloLinking my suggestion https://clojurians.slack.com/archives/CPABC1H61/p1660654508502309?thread_ts=1660653246.056459&amp;cid=CPABC1H61#2022-08-1614:39DerekDoes the inconsistent-alias linter not work with certain string namespaces used in cljs? (Details in thread)#2022-08-1700:40DerekNo, but I’m not sure how to represent a require like “@vanilla-extract/css”#2022-08-1700:50DerekThat leading at-sign seems to be the problem#2022-08-1715:35DerekHow can I throw a symbol like that in my .clj-kondo/config.edn ?#2022-08-1913:58DerekHas anyone figured out how to include a namespace like “@vanilla-extract/css” or anything with a leading “@” inside .clj-kondo/config.edn?#2022-08-1914:14borkdudeSorry for not getting back to you. It might just be a use case that wasn't yet considered for this linter. Issue welcome (+ optionally a PR)#2022-08-1914:15DerekNo worries, hope I didn’t come across rude. I’ll document the issue and perhaps, work on a solve this weekend#2022-08-1914:16borkdudeNot at all rude#2022-08-1913:58DerekHas anyone figured out how to include a namespace like “@vanilla-extract/css” or anything with a leading “@” inside .clj-kondo/config.edn?#2022-08-2223:28lilactownin the hooks docs, under tips & tricks it says you can develop these hooks at the REPL, but doesn't say how to setup your REPL to have clj-kondo on the class path#2022-08-2300:12skylizehttps://clojars.org/clj-kondo#2022-08-2308:16borkdudeJust include it as a library like any library?#2022-08-2315:25lilactownhttps://github.com/clj-kondo/clj-kondo/pull/1783#2022-08-2418:06Drew VerleeIs it possible to call functions from the repl? Or just i bb script my way to having this called on all my dep changes? Also, this is amazing ❤️ .#2022-08-2421:23borkdudeThanks! What prevents you calling this from the REPL?#2022-08-2515:36Drew Verleemaybe nothing, i'll go try 🙂#2022-08-2420:16Drew Verleeis there a way to get clj-kondo to only return errors?#2022-08-2420:29Drew Verleei guess i can easily do this filtering on my end#2022-08-2420:30Drew Verleebut i'm guessing there is a more systmetic way to review at least review these changes. I guess that would mean some sort of emacs integration though? Like a here is a list of warnings tab through them with a approval step if it's automatically changeable.#2022-08-2420:36Drew Verleeor if i want clj-kondo to take the wheel and make all the changes it knows about.#2022-08-2421:22borkdudeyou can grep errors on the command line, there isn't currently something to only output errors, but it's a common enough question to log an issue for#2022-08-2421:23borkdudeclj-kondo doesn't make any changes to your code, it only gives lint warnings. clojure-lsp builds on top of clj-kondo analysis + linting and does fix some of those automatically#2022-08-2515:40Drew VerleeI see there is work on add what looks like some default linting for compojure https://github.com/clj-kondo/clj-kondo/commit/e5f8af54590b084cc119263698bdc786bfc6434f. But it doesn't seem on by default, and i'm not seeing how i enable it. the GET macro is still reporting errors:#2022-08-2515:44Drew Verleedigging up old conversations... https://clojurians.slack.com/archives/CHY97NXE2/p1655757746303809#2022-08-2515:47Drew Verleeadd this to the clj-kondo config will ignore it i hope#2022-08-2515:48Drew Verlee:linters {unresolved-symbol {:exclude [(compojure.api.sweet/GET) ]}} looks like no one built a custom hook, i don't plan on doing it either.#2022-08-2515:51hiredmanThat isn't composure though#2022-08-2515:52Drew Verleethe require is [compojure.api.sweet :as sw]#2022-08-2515:52hiredmanYeah, that is not compojure#2022-08-2515:52hiredmanThat is whatever that sweet api thing built on compojure is#2022-08-2515:54Drew Verleeapologies for the confusion, when i google "compojure" the first thing that comes up is compojure-api and the hello world is (require '[compojure.api.sweet :refer :all]) so i was considering it compojure. because it has the name compojure in it.#2022-08-2515:54Drew Verleeshould have said "compojure.api.sweet"#2022-08-2515:54hiredmanhttps://github.com/metosin/compojure-api is what you are using, https://github.com/weavejester/compojure is what is being referred to as compojure in that commit#2022-08-2515:55Drew Verleeerr maybe i was googling for compojure api, thanks for the clarification.#2022-08-2515:58hiredmanit was an unfortunate choice of name they went with#2022-08-2516:00hiredmanfortunate for them, good for marketing their new (at the time) library, unfortunate for the community now having two easily confusable library names#2022-08-2516:32Drew Verleeis there a way to exclude an entire namespace, that i don't control, from being linted?#2022-08-2516:36Drew Verleelooks like regex might be supported#2022-08-2516:38Drew Verleeor :refer-all https://cljdoc.org/d/clj-kondo/clj-kondo/2020.09.09/doc/configuration#exclude-namespace-in-refer-all-linter#2022-08-2516:40borkdudeif you don't control the namespace, why do you care about linting results for that one?#2022-08-2516:43Drew Verleemy project has a multiple namespaces that require [compojure.api.sweet :as sw] ideally it would be properly linted, but i'm not sure i's worth taking the time to do, so i'm looking for a way to quickly ignore everything from that namespace so it's easier to see other more important/better error reporting. This is working but it's obviously not comprehensive.
{:unresolved-symbol {:exclude
                  
                        [(compojure.api.sweet/GET)
                           (compojure.api.sweet/POST)
                           (compojure.api.sweet/PUT)]}}
#2022-08-2516:44Drew Verleeby "dont' control" i mean, i can't change the namespace that contains the macro. I though that might be relevant to understanding my options.#2022-08-2516:44borkdudeyou can use :output {:exclude-files ["regex"]}#2022-08-2517:59Drew Verleecan you have multiple config.edn's in your project's .clj-kondo directory? it looks like i "somehow" (lsp?) added a /.clj-kondo/prismatic/schema/config.edn#2022-08-2518:00borkdude@drewverlee This happens when you extract configurations from dependencies. They are included automatically#2022-08-2518:00Drew Verleethats what i was hoping happened. ty tyt.#2022-08-2520:53Cora (she/her)hmmm seems like flycheck-clj-kondo is picking the wrong directory to look for the .clj-kondo directory#2022-08-2520:54Cora (she/her)I guess that might be flycheck itself being weird#2022-08-2520:54borkdude🧵#2022-08-2520:54Cora (she/her)👋:skin-tone-2:#2022-08-2520:55borkdudeflycheck runs over a file while setting the current working directory to the file's parent. clj-kondo then searches for the .clj-kondo directory from that directory to the top and takes the first one that it finds#2022-08-2520:57Cora (she/her)so if the file is /foo/bar/baz.clj it would first check /foo/bar/.clj-kondo then /foo/.clj-kondo then /.clj-kondo?#2022-08-2520:57borkdudeyes#2022-08-2520:58Cora (she/her)something is fucky then because it's skipping the deeper-nested .clj-kondo and going one directory up#2022-08-2520:58Cora (she/her)I use doom emacs so it could very well be something doom is doing#2022-08-2520:59Cora (she/her)I'm looking deeper into it#2022-08-2520:59borkdudeI'll be asleep now and will check back tomorrow#2022-08-2521:00Cora (she/her)thanks! sleep well 🙂#2022-08-2521:41Cora (she/her)ok, it's using lsp for clj-kondo and that's finding the wrong project root#2022-08-2914:21Martynas MaciulevičiusHey. I used function format in cljc file and it complains that it's unresolved. It would be a little more helpful if it would say that it doesn't exist in all implementations :thinking_face:#2022-08-2914:32borkdude@invertisment_clojuria There is an open issue for this, to say for which branch the error applies#2022-08-2916:18nateI recently ran into this as well, when making a namespace compatible with clojure and bb. I ended up with this so that the spit inside my-fn is properly resolved:
(ns test
  (:refer-clojure :exclude [spit format]))

(def spit #?(:clj clojure.core/spit))
(def format #?(:clj clojure.core/format))

(defn my-fn
  []
  (spit "output.txt" (format "yay %s" "format")))

(my-fn)
Is there a better way to accomplish this?
#2022-08-2916:39borkdude@nate Try: {:cljc {:features [:clj]} in config.edn : this will only activate linting for the :clj branches#2022-08-2916:45natethat works!#2022-08-2916:47natehm, should it be possible to put that in the namespace config?
(ns test
  {:clj-kondo/config '{:cljc {:features [:clj]}}})

(defn my-fn
  []
  (spit "output.txt" (format "yay %s" "format")))

(my-fn)
clj-kondo --lint test.cljc 
test.cljc:6:4: error: Unresolved symbol: spit
test.cljc:6:23: error: Unresolved symbol: format
linting took 40ms, errors: 2, warnings: 0
#2022-08-2917:45borkdudeno, it's a project-wide config#2022-08-2917:45nateah makes sense, thank you#2022-08-2917:49borkdudethe issue there is that this config has to be known before the file is being being processed#2022-08-3017:24ericdalloIn a hook's code, do I have a way to know the filename being linted?#2022-08-3017:24borkdudeeverything a hook can know is passed in the map as the argument#2022-08-3017:24borkdudeif the filename isn't in there yet, we could add it#2022-08-3017:25borkdudewhy do you need the filename though?#2022-08-3017:26ericdallonice, at Nubank we had some crashes in prod related to use schema.core/with-fn-validation in a production code 😅 , so we are thinking on add a custom lint for that function to check if the filename contains a src (usually, at least for our services, production code)#2022-08-3017:27ericdalloand emit a warning/error to avoid that code go to prod#2022-08-3017:29borkdudeso you would like to discourage with-fn-validation within certain namespaces?#2022-08-3017:30ericdallonot namespaces, because we can't know only by a ns if that's is from test source-path#2022-08-3017:31ericdalloI think we would need the filename or file uri#2022-08-3017:31borkdudeWouldn't that just be something for: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#discouraged-var#2022-08-3017:34ericdalloDamm, didn't know about this one, sounds perfect#2022-08-3017:34ericdallowill take a look, thank you very much#2022-08-3017:36ericdalloActually, we do use it on tests, using that would make the warn for tests as well right? :/#2022-08-3017:38borkdudeyes, but you can make an ns-group for your tests (e.g. all namespaces ending with -test ) and then undo it for the tests#2022-08-3017:38ericdallogot it, sounds good#2022-08-3017:38ericdallowill test it, thanks!#2022-08-3017:53ericdallothe ns-group :pattern is a pattern for the ns right? I think that won't work since we can't know if a ns is a test, for example test/my_service/foo/my_feature.clj (`(ns my-service.foo.my-feature)`)#2022-08-3017:54borkdudeit's a common convention to name test nses foo_test.clj#2022-08-3017:54borkdudebut maybe could also enable a regex based on the file. gotta go now#2022-08-3017:56ericdalloyeah I know, but we have some integration legacy tests not using that convention, I think it'd be convenient to have a file-pattern optional, WDYT?#2022-09-0213:07ericdallo@U04V15CAJ WDYT? would you accept a issue about it? I can try to find some time to implement the file-pattern support if you want#2022-09-0213:08borkdudeissue welcome, + PR#2022-09-0213:49ericdallohttps://github.com/clj-kondo/clj-kondo/issues/1790#2022-08-3113:11sheluchinDoes clj-kondo include any functions that it uses for parsing file contents according to the usage/definition information (`row`, col, etc.) returned by the kondo's analysis? I'd like to get file contents as a collection of its constituent parts and thought there might be something in the code base for it already.#2022-08-3113:47borkdudeRecently @U06BE1L6T added this to the wiki: https://github.com/clj-kondo/clj-kondo/wiki/Analysis-tips-and-tricks#getting-the-source-for-usage-of-a-var#2022-08-3114:48sheluchin@U04V15CAJ thanks, that's a start. As an aside, has there been any discussion about doing deeper function call argument analysis?#2022-08-3114:49borkdudedefine what you mean by this please#2022-08-3115:04sheluchinFor example, for functions taking kwargs, analyse which kwargs are being used in their calls. Or to take it one step further, if a particular argument can be any of a set of static values (boolean, keyword, etc.), do analysis to check which static values are being passed. Does that make sense?#2022-08-3115:05borkdudeThere is also a bit of that in clj-kondo for type checking, but are you asking for this to be exposed in the exported analysis?#2022-08-3115:09sheluchinYeah, I'm interested in getting a distribution of the ways that some given function gets used.#2022-08-3115:10sheluchinArities is the first step, so I'm wondering if there's been any discussion about exposing deeper analysis of that type.#2022-08-3115:12borkdudeI don't think there were any discussions about this before#2022-08-3115:19sheluchinOkay, thanks. I'll ponder it some more. I think there could be some use to it but maybe it's too niche if it hasn't been touched on previously.#2022-08-3115:20borkdudeWhat are you building again? Something public? :)#2022-08-3115:23sheluchinNot quite public yet, but will be soon. I'm building a Clojure code explorer. Largely powered by clj-kondo. The idea is to make it easy to see how libraries are being used in the wild by connecting analysis of publicly available libraries. A learn-by-example thing.#2022-08-3115:24borkdudeCool! This is exactly the thing I was describing at the end of my cognicast interview. Did you pick up the idea there or came up with it independently?#2022-08-3115:25borkdudeI wanted to make a clj-kondo-based crossclj (a service that used to be available)#2022-08-3115:25borkdudeBut as I am doing a lot of other things, I never found time for it, so I'm happy you're doing it :)#2022-08-3115:25sheluchinCame up with it independently. I haven't check out the interview but now I must.#2022-08-3115:26sheluchinIt's a fun little project so far. It's nice when I can use the project to help me build the project 🙂 crossclj.. I'll need to look that up.#2022-08-3115:30sheluchinhttps://github.com/fbellomi/crossclj yep, haven't heard of that either but it sounds very similar.#2022-08-3118:26Noah BogartI've noticed a couple config options that aren't documented. Should they be? • :not-a-function:hook:unexpected-recur#2022-08-3119:05borkdudeprobably, yes. PR welcome!#2022-09-0113:22Noah BogartHow interested would you be in auto-generated docs and default configuration for clj-kondo? I know you're not interested in splitting out the implementation of the rules, but I'm thinking that we could move the config info and documentation into individual files and then merge them as part of the build or release pipeline#2022-09-0114:16borkdudeCould be worth a try, but could also be a lot of work ;)#2022-09-0114:16Noah Bogarthaha yes it would, which is why I'm asking before doing anything dumb 😇
#2022-09-0114:17Noah BogartI'll give it a go, see how fruitful/fruitless it is, and let you know!#2022-09-1104:49Noah BogartI've opened a draft PR to demonstrate colocating linter config and defaults, and their documentation: https://github.com/clj-kondo/clj-kondo/pull/1805. I'd like to get feedback from other clj-kondo hackers and devs as well as @borkdude himself.#2022-09-1104:49Noah BogartI went with a single file instead of multiple files, for ease of initial implementation, but splitting them would be quite easy.#2022-09-1112:43lreadWow, that looks like a real valuable contribution @UEENNMX0T!#2022-09-1113:41Noah BogartI think moving to multiple files is probably best, but then we'd want to bring in parse-edn-metadata-headers from markdown-clj or write our own so we could have edn metadata at the top and raw text examples below:
{:name "Cond-else"
  :keyword :cond-else
  :default-level :warning
  :description "Prefer `:else` as `cond` default branch."}

;;BAD
(cond
  (odd? (rand-int 10)) :foo
  :default :bar)

;; GOOD
(cond
  (odd? (rand-int 10)) :foo
  :else :bar)
#2022-09-1116:04lreadYour use of good/bad in the above example reminded me https://github.com/bbatsov/clojure-style-guide/issues/216#issuecomment-746682308.#2022-09-1116:51Noah BogartSure, the wording can be changed. I just mean to have multiple examples for what is and is not allowed by a given rule. Here's an example from eslint, the de facto javascript linting engine: https://eslint.org/docs/latest/rules/for-direction#2022-09-1116:51Noah Bogart> Examples of incorrect code for this rule:#2022-09-1116:52Noah BogartAnd here's how rubocop presents their linter examples: https://docs.rubocop.org/rubocop/1.26/cops_style.html#styleandor#2022-09-1116:55Noah BogartI’m hoping that by having more space for examples, we could list the alternatives and possibilities for each configuration, so the goal isn't to say definitively “X is good, Y is bad”, but “with linter L configured like this, X is allowed, Y is disallowed”#2022-09-1116:56Noah BogartThanks for the link, I think @U05254DQM is right to avoid “good”/“bad” language#2022-09-1119:53lreadFunnily enough, it was probably bozhidar who wrote both the clojure and rubocop text. simple_smile Not suggesting there is a good or bad wording (see what I did there? :drum_with_drumsticks:). Just remembering some folks thoughtfully talking about it. Perhaps “Lint issue:” vs “Lint free” or something like that?#2022-09-1119:55Noah BogartYeah, I’m not super worried about the specific wording lol. I just want to reduce friction for writing linter documentation, make it slightly easier and fix things like “linter X doesn’t have docs on accident”#2022-09-1120:12borkdude• Problem statement. What I'm missing in this PR is a good problem statement: why are we making a big change, to solve what problem again? Big changes come with risk, so they should be justified • Performance. I haven't looked deeply yet at this PR but one thing I'm always concerned about is performance regressions or changes that affect startup time. Writing a literal map in the impl/config namespace is likely going to be faster than having to re-construct it from a string that has to be parsed from somewhere else on the classpath. And moving this stuff elsewhere also would break the clj-kondo pod (binary) so that would have to be fixed too (can be done, but something to remember). A few thoughts ◦ measure the time difference between loading the current clj-kondo and the clj-kondo with this PR. Also mind the laziness (I think I saw a map somewhere in the reconstructed version of the map): laziness often gives a skewed performance benchmark. So maybe replace those lazy things with mapv etc. ◦ measure how much time it takes to parse and reconstruct the map with a (time ..) expression ◦ Consider leaving the old map where it is and use that as the source of truth, while adding things to it from other places when generating docs ◦ Adding things to the "source of truth" map possible makes it more expensive to merge and merging configs is a thing that happens a lot. So not adding things to the old map when not generating documentation is preferred. #2022-09-1120:46Noah BogartThanks for the thoughts, Michiel, I'll write some stuff up and see what changes #2022-09-1314:42borkdudeSo, I think your approach has benefits, but I also would like it if there would be no impact on the current way of doing things: minimal map literal (merge and loading time). Would it be possible to build the documentation stuff as another map + a deep-merge with the config in impl/config?#2022-09-1315:30Noah Bogartwith the .edn file, on my 2018 mac book pro, it took roughly 2ms to load, read-string the edn file, and perform the transformation. moving it to a clj file makes it cost "nothing" to load, and the transformation step is roughly 0.05 ms.#2022-09-1315:34borkdudeThe .edn file would also require a change to the binary, etc#2022-09-1315:34borkdudeor maybe not since it's a compile time constant...#2022-09-1315:38borkdudethe current state is that it's in a .clj file right?#2022-09-1315:40borkdudeseems good enough then. btw, you can get a tiny bit of perf win if you don't use :keys but just use (:foo ...)#2022-09-1315:40borkdudebut since this is not on a hot path, it doesn't matter#2022-09-1315:41borkdudeAs a last step, can you update the dev.md docs to indicate what people should do when they want to add docs?#2022-09-1315:41borkdudeand/or place some hints in the code if people are going to look for this#2022-09-1315:44Noah Bogarti'm also trying to figure out exactly how to write out what I want/hope to achieve here, which I know is a bad sign for merging, but it's more that it's harder to write about "dev experience" than "user experience". roughly, the process for writing a lint involves touching a lot of places: the specific part of the code that performs the check, the tests, the default config map, and the docs. The code and tests are to be expected, but the default config map and the docs are places where it's easy to make mistakes. For example, the docs disagree with the default config map on the default warning level for one of the lints (i didn't note which one, just used the one in the code). Both the config map and the docs are not in alphabetical order. The docs are missing some lints. Etc. This raises the burden of writing and maintaining the lints because all of these things have to be coordinated, and there's no automated way to know if they're in sync.#2022-09-1315:44Noah BogartYes, right now I have it in a .clj file. lol sorry for writing all that out and missing your other messages#2022-09-1315:46Noah BogartI think it's a little harder to use as a .clj file, but that's mostly due to how we don't have multi-line strings in Clojure.#2022-09-1315:54borkdudeah I see. well, put it in a .edn file then. 2ms is no biggie#2022-09-1409:53borkdudeBtw, I didn't get the ".clj has not multiline strings" comment, how is that different from .edn?#2022-09-1412:43Noah BogartIt’s not, I just found it harder to get indentation correct with additional indentation from the def form and quoting. Purely a personal preference.#2022-09-1413:54borkdudeYou know what. Maybe just a script that checks if all linters have documentation should be enough. And alphabetically sorting the entries (this is not a must for me personally). I prefer writing .md than in .edn.#2022-09-1413:54borkdudeThis is where "start with a problem statements" comes in. This PR starts with a solution without a problem#2022-09-1413:55borkdudeIf the problem is: you might miss writing docs for some linters, there should be various solutions and then a PR#2022-09-1414:16Noah BogartIf that suits you better then I can do that. I think the problem is bigger than "missing docs for some linters", but like I said earlier, it's much harder to quantify "poor dev ex" so I understand. I agree that writing .md is much nicer than writing .edn and it's something I'm frustrated by in this attempt. I'll close this PR and open one focused on adding missing docs and sorting the documentation.#2022-09-1414:16borkdudeThanks. I appreciate it#2022-09-1414:17Noah BogartI'm gonna keep poking at this because I think it's worthwhile, but I'll wait until I have a much better solution. Thanks for all the feedback, I really appreciate your patience and continued help#2022-09-1414:19lread@UEENNMX0T I find working out what problem I am trying to solve in a GitHub issue (or a GitHub discussion) often helps me out. I know I appreciate this kind of thing too on projects I maintain.#2022-09-1414:25Noah Bogarthah Yeah, I generally do that first but jumped the gun here. Oops!#2022-09-1414:37lreadYeah, there have been rumours of me running with scissors too!#2022-09-1104:49Noah BogartI've opened a draft PR to demonstrate colocating linter config and defaults, and their documentation: https://github.com/clj-kondo/clj-kondo/pull/1805. I'd like to get feedback from other clj-kondo hackers and devs as well as @borkdude himself.#2022-09-0217:35Cora (she/her)how would you get clj-kondo to lint a new assertion (is (not-thrown?...) with the same linter for (is (thrown?...)#2022-09-0217:43Cora (she/her)within the context of clojure.test, I mean#2022-09-0217:44borkdudethis is currently not configurable. you could just suppress this symbol with :unresolved-symbol :exclude#2022-09-0217:45Cora (she/her)alright, thank you!#2022-09-0218:09Noah BogartThe way I do this (also seen in https://github.com/clojure-expectations/clojure-test/blob/031f55fe494d3cbf1e77039a41b2b2a60048a11a/src/expectations/clojure/test.cljc#L46) is to write a macro that throws for each new assertion and then refer them. Then, the assert-expr method will expand before the referred var can expand#2022-09-0218:10Noah BogartThis lets you put doc strings on the vars too, which is nice#2022-09-0218:22Cora (she/her)ahhhh that's tricky but workable. I think I'll just suppress the symbol for this tiny usage, though. thanks, Noah!#2022-09-0306:59Jacob EmckenI am getting a expected symbol from clj-kondo for Clojure spec used with test.check (example below). I can't figure out if I am doing it wrong or if I found a sharp edge of clj-kondo.#2022-09-0307:00Jacob EmckenThis works fine:
(spec/def ::a-fn fn?)

(spec/def ::name string?)

(spec/def ::hey
  (spec/keys :req [::a-fn ::name]))

(spec/valid? ::hey {::a-fn identity ::name "Hello"}) => true
#2022-09-0307:02borkdudeCan you post the example with the warning?#2022-09-0307:03Jacob EmckenNow I want to generate test data, for no particular reason other than "I can" (or should be able to) with (gen/generate (spec/gen ::hey)) But it gives me:
; Execution error (ExceptionInfo) at user/eval9271 (form-init5066133147658145143.clj:81).
; Unable to construct gen at: [:user/a-fn] for: :user/a-fn
#2022-09-0307:03Jacob EmckenThen I add:
(spec/fdef ::a-fn
    :args (spec/cat)
    :ret int?)
#2022-09-0307:04Jacob EmckenWhich makes test.check happy... now I can generate test data. But now clj-kondo complains about expected symbol:
(spec/fdef ::a-fn
           ^^^^^^
#2022-09-0307:06borkdudeWhat if you make that a symbol? I didn't know function specs could be made with keywords or if it's maybe accidentally supported #2022-09-0307:07borkdudeA quoted symbol#2022-09-0307:49Jacob EmckenI don't understand how. If I use anything but ::a-fn then how does spec know what I am defining?#2022-09-0307:49lassemaattaPerhaps you should use fspec instead of fdef? :thinking_face: #2022-09-0307:50borkdudeFWIW, the docs for fdef say: > Takes a symbol naming a function#2022-09-0307:50Jacob EmckenI'll look into fspec#2022-09-0307:50borkdudebut I think it may accidentally work for a keyword. So if you try: my-namespace.a-fn it will work per the docstring#2022-09-0308:10Jacob EmckenI could not figure out how to make spec, like my quoted symbol, but the following seems to work:
(spec/def ::a-fn
  (spec/fspec :args (spec/cat)
              :ret nil?))
;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^
;; NOTICE THIS 

(spec/def ::name string?)

(spec/def ::hey
  (spec/keys :req [::a-fn ::name]))

(spec/valid? ::hey {::a-fn println ::name "Hello"})
(spec/explain ::hey {::a-fn println ::name "Hello"})

(gen/generate (spec/gen ::hey))
#2022-09-0308:11Jacob EmckenThanks @U04V15CAJ and @U0178V2SLAY 💜#2022-09-0308:13borkdudeYeah sorry it should be just an unquoted symbol but good that you figured it out #2022-09-0310:17slipsetThis is probably a RTFM, but still: I’ve written a macro like
(defmacro with-foo [foo & body] 
   `(let [~foo ...]
      
to be used as:
(with-foo lol
   (println lol)
What kind of lint-as magic do I need to invoke to let clj-kondo understand that lol is in fact defined in the call to println?
#2022-09-0310:18borkdude@slipset There is a built-in macro similar to this: cljs.test/async#2022-09-0310:21slipsetLovely! Thanks!#2022-09-0416:40andrzejsliwaHey, any idea why on new lein project or deps.edn I have such error from clj-kondo (via Clojure Extras plugin in Intellij IDEA)#2022-09-0416:40andrzejsliwawhen I’m running it manually I got:#2022-09-0416:41andrzejsliwaso I’m guessing that problem is with Clojure Extras, but maybe somebody can confirm#2022-09-0416:44andrzejsliwaswitching from :refer to :as is solving problem… but still on command line is just one warning less for :refer#2022-09-0416:44borkdudeclj-kondo doesn't work very well with multiple :refer :alls#2022-09-0416:46andrzejsliwawhat you would recommend? listening for kondo warnings (replacing with :as or explicit) or disable kondo…#2022-09-0416:47borkdudereplace with :refer [deftest is testing]#2022-09-0416:47andrzejsliwaso this is standard best practice?#2022-09-0416:47borkdudeyes - in CLJS refer :all doesn't even work#2022-09-0416:48andrzejsliwathank you, I will.#2022-09-0416:48andrzejsliwa👍 thanks for hint#2022-09-0616:07Rachel WestmacottHi all, enjoying clj-kondo gratitude !#2022-09-0616:07Rachel WestmacottIs there a line-length linter that I'm too foolish to find?#2022-09-0616:08borkdude@peterwestmacott Thank you! clj-kondo does not lint whitespace or length of lines (currently)#2022-09-0712:47eskosMaybe it’s good to stay away from this debate, line length tends to be a very political and emotion filled subject… 🙂#2022-09-0616:09Rachel WestmacottOkay! - is that deliberate choice, or just it's not seemed important enough yet?#2022-09-0616:09borkdudethe latter#2022-09-0616:10borkdudeI think you could write one in bb maybe ;)#2022-09-0616:11borkdudeI haven't heard many people ask about this, but if you want, you can check if there's already an existing issue or create a new one and then we can see if people have interest#2022-09-0708:39Rachel WestmacottI hope I did that right: https://github.com/clj-kondo/clj-kondo/issues/1794#2022-09-0708:42borkdudeYes! In the original template there is a snippet like "if you like this feature, upvote it with a thumbs up". You could leave that in#2022-09-0708:42borkdudeThen I can sort issues to see what people are most interested in#2022-09-0708:44borkdudeI think the implementation for this would be pretty easy: walk over the whole file input and emit a lint warning when a line is longer#2022-09-0708:45Rachel WestmacottI know nothing about the internals of clj-kondo, but it certainly sounds like a simple thing to check for.#2022-09-0708:49borkdudeso basically, every file being linted passes through here: https://github.com/clj-kondo/clj-kondo/blob/27a12984042afc7dc3d11327f4573a73f51176e3/src/clj_kondo/impl/analyzer.clj#L2725 the input argument is the file contents as string#2022-09-0708:49borkdudeWhen a line is longer than a certain value, you call (findings/reg-finding! ...) and that's basically it#2022-09-0708:51Rachel WestmacottAre you saying this because it is interesting, or because you hope I will submit a PR? (it might work)#2022-09-0708:51borkdudeIf you're up for a PR, sure#2022-09-0708:51Rachel Westmacott(or for some third reason I've not considered)#2022-09-0919:10Rachel WestmacottI had a go at one: https://github.com/clj-kondo/clj-kondo/pull/1802 I hope I've done it right.#2022-09-0919:11borkdude@peterwestmacott Awesome!#2022-09-0919:24borkdudeTested it locally, works!#2022-09-0919:26borkdude#2022-09-0919:26borkdudeI think I'll leave it on for personal use ;)#2022-09-0919:29borkdudeMerged. Congrats and thanks.#2022-09-0920:55Rachel WestmacottThanks!#2022-09-1712:49borkdude@peterwestmacott Have you considered cases like this?#2022-09-1714:31Rachel WestmacottNope!#2022-09-1714:32borkdudeWhat would you do in this case?#2022-09-1714:39Rachel WestmacottI don't know. :thinking_face:#2022-09-1714:39borkdudeWhat do other linters do here?#2022-09-1714:41Rachel WestmacottAgain I don't know. I imagine they complain, because the line is too long.#2022-09-1714:41Rachel WestmacottAre you suggesting that this particular line length might be legitimate?#2022-09-1714:42Rachel WestmacottTo my mind it is too long and shouldn't be allowed, but I can see that pragmatically that could be annoying.#2022-09-1714:42Rachel WestmacottIt seems to point at a fundamental issue with URL length#2022-09-1714:45Rachel WestmacottI could imagine a 'softer' version of the linter that only looked for whitespace beyond the desired line length. That way if your line was too long, but you could argue that you 'didn't have a chance to break it' it would let you off.#2022-09-1714:45borkdude> Are you suggesting... No, I honestly don't know#2022-09-1714:46Rachel WestmacottAfk rn or I'd check on lein bikeshed to see how it behaves, but I'd put money on it complaining.#2022-09-1714:48borkdude@U051BLM8F: What does rubocop do in cases of long urls that can't be broken?#2022-09-1714:48Rachel WestmacottOne could say "use a URL shortener" or "link to your issuer tracker and put the super long URL in there"#2022-09-1714:48borkdudeor long strings for that matter#2023-01-1505:27didibusI know some linters make an exception for lines with no space in them, such as a url#2022-09-0712:09sheluchinHow about a linter to warn when using the fully-qualified version of a keyword when there exists an alias for that same namespace?#2022-09-0812:03sheluchinMade an https://github.com/clj-kondo/clj-kondo/issues/1800 in case there is more interest.#2022-09-0812:42borkdudesounds good#2022-09-0809:54robert-stuttafordhey @borkdude 🙂 would it be possible for the babashka pod for clj-kondo to reach version parity with the version released on clojars / homebrew, perhaps?#2022-09-0809:55robert-stuttaford
Type:     java.io.FileNotFoundException
Message:  
#2022-09-0809:55borkdudeabsolutely, I'm working on a new clj-kondo version now and will bump the pod after that#2022-09-0809:55robert-stuttafordamazing thank you sir#2022-09-0813:02borkdudedone#2022-09-0814:56robert-stuttafordyou rock!#2022-09-0812:42borkdude#2022-09-1118:29quollSince I'm new to clj-kondo, I'm wondering if someone has advice for configuring around a construct... I'm calling a macro inside conditional compilation, where the macro generates a record definition that satisfies a protocol. clj-kondo is seeing one of the function definitions in this as a call to the function, and reports an error. The error in this case is that the function expects 3 args but that it's being called with 2 (what it's seeing at the arg vector and a let block that forms the body of the function). Any suggestions on how I might inform the linter that this is not a problem, please?#2022-09-1118:29quollThe code in question is at: https://github.com/quoll/asami/blob/a469640790e272ecad6d47bb00a687a3b0291722/src/asami/cache.cljc#L120#2022-09-1118:33borkdudeHere's what you can do with macros: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#unrecognized-macros#2022-09-1118:33quollThank you!#2022-09-1118:34borkdudepossibly lint-as with deftype will work#2022-09-1118:39quollI did it with defrecord, and yes, it works well. Thank you!#2022-09-1121:26quollI know I'm being a bit needy here, but... Any idea why this causes a problem? https://github.com/quoll/asami/blob/a469640790e272ecad6d47bb00a687a3b0291722/src/asami/durable/flat_file.clj#L118#2022-09-1121:27quollIt's a call of (recur 1) which is asking to restart a function that's defined in a letfn and takes a single argument.#2022-09-1121:28quollBut it says:
src/asami/durable/flat_file.clj:118:25: error: recur argument count mismatch (expected 0, got 1)
src/asami/durable/flat_file.clj:135:33: error: recur argument count mismatch (expected 0, got 1)
#2022-09-1121:31borkdude> I know I'm being a bit needy here Not at all, please do ask all the questions you want#2022-09-1121:31borkdudeI'm trying to repro that...
$ clj-kondo --lint - <<< '(letfn [(foo [x] (recur 1))])'
<stdin>:1:10: warning: unused binding foo
<stdin>:1:15: warning: unused binding x
linting took 15ms, errors: 0, warnings: 2
:thinking_face:
#2022-09-1121:32borkdudeIt could be a bug. Is it possible to narrow this down to a smaller example?#2022-09-1121:34quollI see that there was an https://github.com/clj-kondo/clj-kondo/issues/131 that was also a problem with arities in letfn, and it referred to something happening in #129#2022-09-1121:34quollHmmm, I can try#2022-09-1121:34borkdudeI think I know what's going on, it's a defrecord + letfn thing#2022-09-1121:35borkdude
$ clj-kondo --lint - <<< '(defrecord Foo [] clojure.lang.ILookup (valAt [_ _] (letfn [(foo [x] (recur 1 2))])))'
<stdin>:1:62: warning: unused binding foo
<stdin>:1:67: warning: unused binding x
<stdin>:1:70: error: recur argument count mismatch (expected 0, got 2)
#2022-09-1121:35quollyou're faster than I 🙂#2022-09-1121:35borkdudeso what's happening here: clj-kondo compensates for the recur in valAt and subtracts the "this" argument but it forgets to turn that off for the letfn function#2022-09-1121:36borkdudeI'll file a bug. I you can ignore this with #_:clj-kondo/ignore#2022-09-1121:36quollMakes sense. Thank you!#2022-09-1121:36borkdudeso like this: #_:clj-kondo/ignore (recur 1)#2022-09-1121:37quollin the config file??#2022-09-1121:37borkdudein the code#2022-09-1121:38borkdudebefore the false positive you can insert #_:clj-kondo/ignore#2022-09-1121:39quollOIC. Thank you#2022-09-1121:39quollI was using the sledgehammer approach#2022-09-1121:40quoll:linters {:invalid-arity {:skip-args [clojure.core/letfn]}}#2022-09-1121:40borkdudeor you could just use let + fn ? :) I usually don't use letfn at all unless I need mutually recursive functions which I never do#2022-09-1121:42borkdudePosted the issue here: https://github.com/clj-kondo/clj-kondo/issues/1806 - I'll fix it before the next release (usually within a month)#2022-09-1121:43quollWhile that's reasonable, this code has been around a while, and there's nothing actually wrong with letfn, so I'll leave it for now#2022-09-1121:43borkdudefair enough#2022-09-1121:44borkdudeand I also discovered that it's not just about letfn :) let+ fn has the same bug#2022-09-1121:57quollany suggestions on how to create a minimum reproduction that leads to error: Unresolved symbol: format ?#2022-09-1121:58borkdudeis this .cljc ?#2022-09-1121:58quollyes! Thank you#2022-09-1123:00quollThis is an awkward one. The following fails, claiming that fn is called with 1 arg but expects 2: https://github.com/quoll/asami/blob/a469640790e272ecad6d47bb00a687a3b0291722/src/asami/query.cljc#L350#2022-09-1123:01quollThe map is creating a transducer that gets applied to a pair of seqs, so I can see how this might confuse the linter#2022-09-1123:02quollBut I can't reproduce it on a smaller scale. For instance, this passes:
(sequence (comp (map (fn [a b] [a b])) cat) [1 2 3] [4 5 6])
#2022-09-1123:03quollSo too does code that doesn't work:
(sequence (comp (map (fn [a b c] [a b c])) cat) [1 2 3] [4 5 6])
#2022-09-1123:05quollWhen I pass that to the linter, it works fine:
$ echo '(sequence (comp (map (fn [a b c] [a b c])) cat) [1 2 3] [4 5 6])' | clj-kondo --lint -
linting took 10ms, errors: 0, warnings: 0
#2022-09-1123:05quollThat's despite the code actually failing:
user=> (sequence (comp (map (fn [a b c] [a b c])) cat) [1 2 3] [4 5 6])
Execution error (ArityException) at user/eval1 (REPL:1).
Wrong number of args (2) passed to: user/eval1/fn--137
#2022-09-1123:06quollso, my minimal examples all pass the linter, but the actual code incorrectly fails 🙂#2022-09-1123:07quollI need one of these stickers... https://etsy.com/listing/1181583724/idk-what-im-doing-as-a-service-glossy#2022-09-1202:54quollSpeaking of letfn, it seems that the clj-kondo really doesn't like the plumatic schema version of letfn#2022-09-1209:16borkdude@U051N6TTC clj-kondo has built-in support for some schema things, but I don't think letfn has ever come up.#2022-09-1209:16borkdudeif you could write it as a let + s/fn, it might be supported right now#2022-09-1209:24borkdudeAbout the invalid arity bug, it seems like clj-kondo is indeed confused about transducer vs. seq. This yields a similar but valid warning:
(comp (map (fn [results _]
             (map identity results))
           [])
      cat)
#2022-09-1209:24borkdudeif you remove the [] the warning disappears (as it should)#2022-09-1209:33borkdudeI narrowed the example down to this in your ns:
(defn disjunction
  "Implements an OR operation by repeating a join across each arm of the operation,
   and concatenating the results"
  [graph
   part
   [_ & patterns]] ;; Discard the first element, since it is just the OR operator
  (sequence
   (comp (map (fn [_results _cols]))
         cat)
   []
   []))
but when I move this example to a standalone file, the error disappears
#2022-09-1209:35borkdudeso what I'm trying now is to remove stuff until the error disappears#2022-09-1209:40borkdudeOh lol, it's related to .cljc - repro:
(ns query)

(defn disjunction
  [_graph _part]
  (sequence
   (comp (map (fn [_results _cols]))
         cat)
   []
   []))
I think it's just a matter of adding cljs.core somewhere to fix it :/
#2022-09-1209:41borkdudeThanks for finding those bugs :-D#2022-09-1209:43borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1807#2022-09-1209:44borkdudea workaround for now:
(comp (map #_:clj-kondo/ignore (fn [_results _cols])) cat)
#2022-09-1213:23quollThat’s what I did. Thank you for looking at it!#2022-09-1314:16Noah BogartLint idea: there's :unresolved-namespace (https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-namespace), but it doesn't raise any flags when a fully qualified symbol's namespace is required and aliased or the symbol is referred. I'd love a linter that says "if an alias exists, warn on not using the alias. if the symbol is referred, warn on using the full namespace". Something like :qualified-symbols? To allow for fully configuring it with different styles: :fully-qualified would mean you have to write clojure.string/join , :prefer-alias would mean you have to write str/join if [clojure.string :as str :refer [join]] , :prefer-refer would mean you have to write join if [clojure.string :as str :refer [join]], :any would mean either str/join or join is fine if [clojure.string :as str :refer [join]] .#2022-09-1314:23Noah Bogarthmm idk about the styles lol, probably just have an order of preference: referred -> alias -> fully qualified.#2022-09-1314:26borkdudeThere is a recent issue posted about this#2022-09-1314:26borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1800#2022-09-1314:26Noah Bogartoops! thank you#2022-09-1314:41borkdudeno problem :)#2022-09-1321:44escherizeThere is a clojure convention to use s, n, coll, m, and others to refer to the type of a function argument. Has there ever been any thought to transforming those kind of arguments into :type-mismatch linting rules? I am asking if it exists before I start building such a thing to see if it’s worthwhile.#2022-09-1321:45escherizeThat’s 1 example of ‘baked in’ type data. There’s also e.g. prismatic schema s/defn that gives typing info. Also I know that malli is able to write type-mismatch rules from its function schemas, which is pretty neat#2022-09-1408:42flowthingIs there a way to tell clj-kondo to think of a .cljc file as a .bb and .clj file instead of a .clj and .cljs file? For example, given test.cljc:
(Character/isWhitespace "")
clj-kondo says that Character is an unresolved namespace even though both Babashka and Clojure support it.
#2022-09-1408:43borkdude@flowthing You can do :cljc {:features [:clj]} to only lint .cljc as .clj#2022-09-1408:43borkdudewhich I use typically for bb-compatible stuff#2022-09-1408:44flowthingCool, that works, thanks. :thumbsup:#2022-09-1414:01sheluchinI notice that var-definitions sometimes contain nil values for :row and :col. I'm wondering if this might be a bug. Details in 🧵#2022-09-1414:02sheluchinFor example, this definition https://github.com/fulcrologic/fulcro-rad-semantic-ui/blob/c22ab504d6030e1174a3166e1f1e6f5f5f597f11/src/main/com/fulcrologic/rad/rendering/semantic_ui/autocomplete.cljc#L31-L41 produces the following analysis data:
{:fixed-arities #{1}
       :end-row nil
       :name-end-col 31
       :name-end-row 31
       :name-row 31
       :ns com.fulcrologic.rad.rendering.semantic-ui.autocomplete
       :name normalize-options
       :defined-by clojure.core/defn
       :lang :clj
       :filename "... /resources/repos/fulcrologic/fulcro-rad-semantic-ui/src/main/com/fulcrologic/rad/rendering/semantic_ui/autocomplete.cljc"
       :col nil
       :name-col 14
       :end-col nil
       :row nil}
#2022-09-1414:02borkdudemight be a bug#2022-09-1414:03sheluchin@U04V15CAJ I thought so, but wanted to check with you first just in case. Doesn't look like a result you would expect for such a definition?#2022-09-1414:04sheluchinNotice that other location fields do contain a value.#2022-09-1414:09borkdudeAs I said, might be a bug#2022-09-1414:13borkdudeFeel free to post an issue, not sure why it happens. I or you or someone else needs to take a look#2022-09-1414:13sheluchinAlrighty, thank you. I'll have a shot at a fix.#2022-09-1416:52sheluchin@U04V15CAJ I have a fix but I don't know how to write a test for it and I don't fully understand why the code is written the way it is, probably because I haven't studied how rewrite-clj works. The problem is https://github.com/clj-kondo/clj-kondo/blob/787a8f75df65d82794c1cc8407d88a7b93a4c298/src/clj_kondo/impl/namespace.clj#L100-L104. reg-var! expects to find the missing location fields to be in the (meta expr), but it's in the passed in metadata for this definition and others like it which fail. Replacing the let binding with:
expr-row (or (:row m) (:row metadata))
fixes it. Any suggestions?
#2022-09-1416:56borkdudeI see. I'm not sure why we don't always use "metadata", this is a bit messy#2022-09-1416:59borkdudeI'm fine with adding or there, if that works#2022-09-1417:02sheluchinSeems to. I'll do a bit more manual testing, but not sure how to unit test such a case because the var definition I'm testing against is a custom macro.#2022-09-1417:02borkdudewith a hook or so?#2022-09-1419:13sheluchinSorry, I don't yet understand how to do that. There is already a hook for defmutation that Fulcro https://github.com/fulcrologic/fulcro/blob/6b53c03787344db00cd7f4b92f779e861cc2fcb3/src/clj-kondo/clj-kondo.exports/com.fulcrologic/fulcro/com/fulcrologic/fulcro/clj_kondo_hooks.clj#L4. Is there some way I can leverage that within the tests? I don't mean to bother you with this. If you would prefer I can just open a ticket or PR with the findings and solution so far.#2022-09-1419:14borkdudeI was just asking, how the custom macro was handled in clj-kondo#2022-09-1419:14borkdudeyou can take a look at the hook tests how to do this#2022-09-1419:17borkdudeIt could also be a sign that the hook doesn't properly attach the location metadata#2022-09-1419:18sheluchinGood point. Reading through the hooks workshop made me wonder why the meta doesn't include the location information anyhow.#2022-09-1421:06sheluchinThat does look to be the case here. The location meta is on the incoming node but not the return value. Maybe all the (or (:name-col metadata) (:col metadata)) -like code in reg-var! is there just in case of situations like this?#2022-09-1421:07borkdudePerhaps ... it's a while ago since I touched that#2022-09-1421:07borkdudeBut I think a location is always better than none :)#2022-09-1422:14sheluchinA wrong location could be worse than none :man-shrugging: As for the tests, I'm looking at clj-kondo.hooks-test, but it's not so clear to me. I'm to define a simplified hook similar to Fulcro's defmutation and put it either in a string right in the test, or in corpus/hooks, and then use it in a call to lint! to assert against?#2022-09-1422:15sheluchinBTW, there are quite a few libraries out there that produce such analysis results. Maybe there should be a warning or something somewhere?#2022-09-1422:15borkdudethere might also be tests in analysis_test regarding hooks, I'm not sure#2022-09-1422:17sheluchinThere is one https://github.com/sheluchin/clj-kondo/blob/787a8f75df65d82794c1cc8407d88a7b93a4c298/test/clj_kondo/analysis_test.clj#L938-L956#2022-09-1422:17borkdudeah good, well, similar to that one then ;)#2022-09-1422:18borkdudeyou could also put the code in a directory in corpus if you prefer that#2022-09-1511:01sheluchinhttps://github.com/clj-kondo/clj-kondo/issues/1812 There's an issue for it. I think I have a fix PR as well. Thank you for the guidance, @U04V15CAJ 🙏#2022-09-1511:33borkdudeMerged, and thank you!#2022-09-1415:13Jacob EmckenI have a ClojureScript project (in Calva) where I am getting a Unused public var caused by the "entry point" to the project. How do I tell the linter to accept that nothing (inside the project) is referencing this function? I've tried adding the following to .clj-kondo/config.edn to no avail:
{:linters {:clojure-lsp/unused-public-var {:level :warning
                                           :exclude #{my-ns/handler}}}}
While adding the following in front does indeed make "the problem" go away... but I would like these things outside the code:
(ns my-ns)

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn handler
...
#2022-09-1415:16borkdudeUnused public var is not a clj-kondo feature but a #lsp feature. Can you post your question there? I'm not sure how that config works. Or maybe @UKFSJSM38 can reply here 🧵#2022-09-1415:20Jacob EmckenOh, I was just reading this example here (which references .clj-kondo/config.edn), so I just assumed 😬 https://clojure-lsp.io/settings/#clojure-lspunused-public-var#2022-09-1415:20Jacob Emckenthanks anyway#2022-09-1415:21borkdudeyeah, it's a custom linting rule#2022-09-1415:21borkdudeit's fine to ask the question here as well, but you might get better replies in #lsp#2022-09-1415:35ericdalloOut of curiosity @USW6URK47, what or where calls that handler funcion?#2022-09-1415:37Jacob Emckenan AWS lambda (Node.js)#2022-09-1415:39Jacob Emckenit is built with Shadow-cljs:
...
:builds {:lambda {:target  :node-library
                  :exports {:handler my-ns/handler}
...
#2022-09-1415:40ericdalloI see, so it comes from shadow, I'm wondering if we could get analytis from shadow edn as well @U04V15CAJ in the future along with bb.edn#2022-09-1416:38borkdudeWasn't the original question why the config didn't work?#2022-09-1416:52ericdalloI mean, if we have analysis on shadow-cljs.edn , then we would know that function is being called there, so users wouldn't need to specify which function they want to exclude from linter#2022-09-1416:53borkdudesure, but excluding should work no matter what#2022-09-1416:54ericdalloah yes, excluding via code and config should work indeed, @USW6URK47 just add the linter config on .clj-kondo/config.edn as mentioned https://clojure-lsp.io/settings/#clojure-lspunused-public-var#2022-09-1416:57borkdude@UKFSJSM38 He already did that. That was the original issue: that this didn't work for him. See original post.#2022-09-1417:00ericdalloGot it, sorry, I misread the question. @USW6URK47 Hum, it does seems to work for me with:
(my-ns)

(defn foo [])
.clj-kondo/config.edn
{:linters {:clojure-lsp/unused-public-var {:exclude #{my-ns/foo}}}} 
Or
{:linters {:clojure-lsp/unused-public-var {:exclude #{my-ns}}}} 
#2022-09-1417:00ericdalloMake sure to re-edit de buffer after changing a config to re-lint the file#2022-09-1417:01ericdallo(BTW, that sounds like a good nice to have, clojure-lsp could re-lint the project when user changes a config.edn: https://github.com/clojure-lsp/clojure-lsp/issues/1247)#2022-09-1504:59Jacob EmckenI found my issue... though I don't understand why it would have any effect at all 😮 I had something commented out like so:
{:linters {:clojure-lsp/unused-public-var {:exclude #{my-ns/foo}
                                           #_#_:exclude-regex #{"my-ns\..*-test"}}}}
#2022-09-1505:00Jacob EmckenWhen I remove #_#_:exclude-regex #{"my-ns\..*-test"} it works. Thanks for your patience, both#2022-09-1505:48Jacob Emcken:thinking_face: I figured it out... I was tricked by the (single) back-slash#2022-09-1800:08ericdalloAbout https://github.com/clojure-lsp/clojure-lsp/issues/1247, this was done on master :) Every time user save a clj-kondo or lsp config, we re-lint all opened files so the UX is smoother#2022-09-1517:10sheluchin@borkdude I almost have a fix for #1758, but just one quick question. What is going on https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/overrides.clj#L49-L57? Why is it assoc'ing cljs.core into both [:cljc :defs cljs.core :clj ...] and [:cljc :defs cljs.core :cljs ...] (both :cljs and :clj)?#2022-09-1517:41borkdude@alex.sheluchin This has to do with some things being both functions and macros in CLJS#2022-09-1518:58sheluchinOkay, that makes sense. I can't seem to find any examples of how to get the :var-definition of something from clojure.core to compare it against the overrides in a test.#2022-09-1519:21sheluchinAh, got it now.#2022-09-1614:55sheluchin@borkdude I put the PR up for #1758. I don't know if putting the overrides check right in reg-var! is a great idea in terms of performance. The other options would be to get the overrides map higher up in the call chain and pass it down to reg-var!, either in a new parameter, or attached to ctx.#2022-09-1614:58sheluchinHmm, build failed :thinking_face:#2022-09-1615:01borkdudeMaybe you "fixed" the analysis which expects a specific result :-D#2022-09-1615:03borkdudeonly lein test :only clj-kondo.analysis-test/analysis-test is failing#2022-09-1615:21sheluchinI'm getting the same result on master though.#2022-09-1615:22borkdude@alex.sheluchin This is likely an effect of what your changes do to what's stored in the cache#2022-09-1615:22borkdudeTry rm -rf .clj-kondo/.cache#2022-09-1615:30sheluchin@borkdude indeed, that was it. But the test also passes back in my branch after:
✔ ~/repos/clj-kondo [add-overrides-to-reg-var L|…3]
$ rm -rf .clj-kondo/.cache/

✔ ~/repos/clj-kondo [add-overrides-to-reg-var L|…3]
$ clojure -M:test -v clj-kondo.analysis-test/analysis-test
Ran 1 tests containing 37 assertions.
0 failures, 0 errors.
#2022-09-1615:31borkdudeyou mean, getting rid of the analysis fixed your problem?#2022-09-1615:31borkdudeperhaps run all tests again#2022-09-1615:32borkdudeit is likely that analyzing clojure.core will produce the problem#2022-09-1615:32borkdudeand this is done during the tests#2022-09-1615:36sheluchinYep, that's it. Okay, thanks for the tips. I gotta run for now but I'll fix it when I get back.#2022-09-1623:11sheluchinI'm not sure what's going on with the builds but I believe it's fixed.#2022-09-1519:48grzmI'm seeing what looks like config caching when running clj-kondo. The behavior I'm seeing: • clj-kondo --lint src in directory I haven't run clj-kondo in before. No .clj-kondo directory in pwd. • see undefined vars from a dependency (due to symbols being generated at run-time) • create a .clj-kondo/config.edn file which includes {:config-paths ["../some-dependency/.clj-kondo"]}. some-dependency/.clj-kondo/config.edn excludes those dynamically created vars • clj-kondo in original directory no longer complains about the undefined vars. • rm -rf ./clj-kondo/ to try to reproduce the original undefined vars message • clj-kondo --lint src still no has no complaint about the original undefined vars I know this has to be user error. I haven't been able to create a small repro case yet (and the actual code is internal so I don't feel comfortable sharing it here). Is there clj-kondo config possibly getting cached someplace else?#2022-09-1520:05borkdudeNot that I know of, but perhaps you also have a config in your home dir?#2022-09-1520:17grzmI do. I’ll delete that and try again. FWIW, both a coworker and I are seeing the same behavior. I hate asking for help with such vague details. I’ll see how else I can slice this into smaller pieces.#2022-09-1520:19grzmDoes clj-kondo look for .clj-kondo/config in parent directories?#2022-09-1520:25grzmOkay. I think I found out what’s going on. The results are being returned in different orders, so what was apparently “missing” is actually just returned in a different location.#2022-09-1520:27grzmActually, I don’t know if that’s it, either.#2022-09-1520:38borkdudeYes, clj-kondo looks in parent directories for .clj-kondo dirs#2022-09-1520:38borkdudethe first parent .clj-kondo directory is considered the project root#2022-09-1521:08grzmI think that may have played a role in what I was seeing. Thanks for confirming.#2022-09-1521:10grzmThe last piece I need to track down (some other time) is why I’m not seeing a :lint-as getting transitively pulled in from a referenced clj-kondo/config.edn. Too many plates spinning right now to dig into that when I can patch it with a little duplication.#2022-09-1521:10grzmCheers!#2022-09-1617:33borkdudeA bikeshed for y'all: What would be a good name for a linter that checks if a var (referenced via symbol) already has an alias?
(require '[clojure.string :as str[)
clojure.string/join ;; Namespace clojure.string has alias: str
The PR is ready but the name is something that might need improvement. We started with :existing-alias but I wanted var or symbol in the name since we will have a similar linter for keywords. So now we have :aliased-namespace-symbol (indicating that the namespace of the symbol has an alias) I think we could do better though. This is where you come in!
#2022-09-1617:34borkdude🧵#2022-09-1618:13Darin Douglass:namespace-has-alias? IMO it’s less about keywords / vars and more about the fact that you’ve specified a fully-qualified namespace when you’ve already aliased it before#2022-09-1618:14lread:use-ns-alias-on-symbol recommends the action that should be taken… but maybe you wan’t to describe the problem? :not-using-ns-alias-on-symbol Or maybe you a hint? :ns-alias-available#2022-09-1618:14Darin Douglassi like that last one#2022-09-1618:15lreadYours is good too @U02EA2T7FEH!#2022-09-1618:40Noah Bogarti like when the the linters have "positive" names, action or rule. i don't like when the name has "no" or "don't" or "not" in the same, cuz it makes it harder to know how to configure it to make it work correctly#2022-09-1618:54sheluchin:unused-ns-symbol-alias I'm not sure I see the value in using a different linter message for keyword and symbol aliases.#2022-09-1618:57sheluchinI like :ns-alias-available. Maybe :ns-alias-defined#2022-09-1619:40Noah Bogarti initially thought we didn't need to separate symbols and keywords, but i feel like giving folks more control of granularity is good#2022-09-1619:44borkdudeHmm yes, :symbol-ns-alias-defined and :keyword-ns-alias-defined maybe?#2022-09-1619:49sheluchinThose work. I guess a different message for both would at least simplify things for implementing the cycle action for https://github.com/clojure-lsp/clojure-lsp/issues/1128 and its symbol counterpart.#2022-09-1620:01skylizesymbol-quailfied-without-existing-alias#2022-09-1620:02borkdude:alias-eligible-symbol and :alias-eligible-keyword ;)#2022-09-1620:03borkdude^ I kinda like those#2022-09-1620:26Darin Douglassalias there reads more like a verb to me than a hyphenated adjective /me inhales deeply in bliss; nothing like some quality bike shedding to end the week#2022-09-1620:28Noah Bogartheh I guess I'll suggest a variation on my original choice:`existing-namespace-alias` . I feel it's short and punchy: "there exists an alias for the namespace referenced here"#2022-09-1620:31lreadOh that’s not a bad point. Could just talk about the namespace and not the keyword or symbol. :namespace-is-aliased if that doesn’t conflict with other linter names.#2022-09-1620:52borkdudeyou could not talk about symbol or keyword, but we want two different linters for those, so you should talk about them :)#2022-09-1620:53borkdudeI like :namespace-is-aliased#2022-09-1620:53borkdudeor just :aliased-namespace#2022-09-1620:54borkdude:aliased-namespace-symbol and :aliased-namespace-keyword then?#2022-09-1620:59skylize:forsaken-symbol-alias :forsaken-keyword-alias#2022-09-1620:59borkdudeoooh hmmm :)#2022-09-1621:01lreadOk, then maybe something more personalized: :for-the-love-of-pete-there-is-an-alias-for-this-namespace-just-use-it-already-lee
#2022-09-1621:19borkdudelol, I didn't realize we already have :aliased-namespace-symbol https://clojurians.slack.com/archives/CHY97NXE2/p1663361698943839?thread_ts=1663349616.937209&amp;cid=CHY97NXE2 I guess we'll just keep it like this then :) /cc @UEENNMX0T#2022-09-1621:39lreadLadies and gentlemen, a perfect bikeshedding session has come to a close!#2022-09-1708:36borkdudeThe bikeshed continues! I'd say the warning for this linter should be on the symbol, not on the "call" (the surrounding list): Right?#2022-09-1712:40skylizeYes#2022-09-1712:41borkdudeI'll fix that now#2022-09-1712:41skylizeIt should not even matter if there is a "call".#2022-09-1712:41borkdudeindeed#2022-09-1712:42borkdudeThat already works for normal symbols#2022-09-1713:00borkdudefixed on master#2022-09-1822:56Noah BogartAh heck, putting it on the call itself is obviously the right move, idk why I didn’t do it. Thanks for catching and fixing it.#2022-09-1619:58Noah BogartI'm using timbre for logging along with the json appender library, and the json appender library requires that the log inputs are formatted a specific way. I wrote a hook (`taoensso.timbre/log`) for timbre's logging functions that works on all of them. Is this part avoidable or am I stuck listing all of them manually?
{:hooks {:analyze-call {
                        taoensso.timbre/debug taoensso.timbre/log
                        taoensso.timbre/error taoensso.timbre/log
                        taoensso.timbre/fatal taoensso.timbre/log
                        taoensso.timbre/info taoensso.timbre/log
                        taoensso.timbre/report taoensso.timbre/log
                        taoensso.timbre/trace taoensso.timbre/log
                        taoensso.timbre/warn taoensso.timbre/log
                        }
#2022-09-1620:03borkdudethis is not avoidable :)#2022-09-1719:22borkdudeI'm writing a new linter to find unused values... and yikes, I found one in clj-kondo... One of the category: how could this ever have worked#2022-09-1906:56eskosThe unfortunate answer is that since it hasn’t worked, now this same behavior is probably scattered across the relevant code paths making the whole thing a bit more complex… 🙂#2022-09-1720:18Noah BogartCan’t wait to turn this on in my production code. How does it know what is or is not a pure function? #2022-09-1720:19borkdudeIt has a list borrowed from our friends at #eastwood called var-info.edn#2022-09-1722:06borkdude😎 https://github.com/lambdaforge/datalog-parser/issues/26#2022-09-1722:19Noah BogartDoes clj-kondo do anything different than rewrite-clj when parsing?#2022-09-1722:20lreadYup!#2022-09-1722:21lreadIt entirely skips whitespace and I think it also parses metadata differently.#2022-09-1722:21Noah BogartAre the differences documented anywhere?#2022-09-1722:23lreadHmm… there is some mention of the whitespace thing in https://github.com/clj-kondo/clj-kondo/blob/1e4d23fd03659342cfd4b6ccc7eded59fc68ff3e/doc/hooks.md.#2022-09-1722:24lreadIt might also deal with namespaced maps differently. I think rewrite-clj got inlined (then customized) from rewrite-clj v0.#2022-09-1722:32Noah BogartAh thank you. I’m working with rewrite-clj for that pattern matching library i mentioned the other day but realized once I started that there are probably differences#2022-09-1812:41borkdudeok, here's the new :unused-value linter. Please try it out locally if you can. https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unused-value#2022-09-1816:52Ben Slessshould kondo highlight tag metadata as unresolved symbols? i.e. (a ^foo b), with a being a macro which abuses metadata 🙂#2022-09-1816:53borkdudeit will do that if it doesn't know what foo is - doesn't it?#2022-09-1817:00Ben SlessIt highlights foo currently as unrecognized symbol. • is there a way to ignore it for one specific macro if it appears as metadata? • should unrecognized symbols as tags be highlighted?#2022-09-1817:01Ben SlessIf so, why not highlight unrecognized-tag for ^{:tag "foo"}?#2022-09-1817:06borkdudeis there a way: not currently they are warned about as they are usually (99%+ of the time) referring to Java classes. except in macros where people (ab)use them differently ;)#2022-09-1817:07borkdudeif the names in those tags are a limited set, you could just suppress them in the unresolved symbol config#2022-09-1817:07Ben Slessthey aren't limited, I'm trying to make life slightly more convenient for myself with spec's cat and alt#2022-09-1817:08Ben Sless
(defmacro |
  [& ks]
  `(s/alt 
#2022-09-1817:09borkdudeand how does the usage look like?#2022-09-1817:09Ben Slessfor cat I want the default name to be either blank or taken as the name of a keyword reference, with the option to provide it by metadata:
(% #{:find} ^find (| ::find-rel ::find-coll ::find-tuple ::find-scalar))
#2022-09-1817:10Ben Slessit expands to
(s/cat :_ #{:find} :find (| ::find-rel ::find-coll ::find-tuple ::find-scalar))
#2022-09-1817:10borkdudewhy not use ^:find ?#2022-09-1817:10Ben Slessand (| ::a ::b) expands to (alt :a ::a :b ::b)#2022-09-1817:11Ben Slessbecause that's {:find true} in the metadata#2022-09-1817:11Ben Slessso I need to play some other tricks, like using a fully qualified symbol and filtering on the namespace#2022-09-1817:11Ben Slesswhich is what I ended up doing#2022-09-1817:12Ben Slessbut the code is ugly and ad-hoc#2022-09-1817:12borkdudeor maybe more explicit: ^`{:spec :find}`#2022-09-1817:12borkdudein my experience with these kind of macros: I always regret these nifty tricks 6 months later#2022-09-1817:12Ben SlessI'm trying to square this circle to end up with less typing, not more#2022-09-1817:13Ben Slessfor alt it's easy, for cat if I have to do lots of backflips I'd rather not#2022-09-1817:15Ben SlessTrying to hit on a syntax which looks a bit more like bnf#2022-09-1817:17borkdudeYou could try to write a kondo hook which removes the tags so kondo won't see then or just ignore all unresolved symbols in your macro with a config #2022-09-1820:40sheluchinWould it be possible/helpful to have a linter to warn against returning a value where it would always be discarded? Like returning a literal value at the end of a doseq and other similar situations.
(doseq [x (get-all-x)]
  {:result (foo x)})
#2022-09-1820:43borkdude@alex.sheluchin There is a new linter on master called :unused-value which should warn if you use a pure function in doseq as the return value. But it doesn't work yet for a map literal. Perhaps you can file an issue. I can look into that, or if you want, you can do it yourself#2022-09-1820:45sheluchinYes, that new linter is what gave me this idea. I haven't turned it on just yet and didn't realize it would warn about situations like that. Thanks, @U04V15CAJ. I'll make an issue about the enhancement for literal returns.#2022-09-1911:36sheluchinLooks like the var-info.edn list from Eastwood could also be used to implement https://github.com/clj-kondo/clj-kondo/issues/1757#2022-09-1911:38borkdudeyeah#2022-09-1911:39sheluchinNice, maybe I'll try to implement that if no one else gets around to it by then.#2022-09-1914:27borkdude😎 https://twitter.com/borkdude/status/1571867993922994176#2022-09-1914:37lreadOh… being the king of typos, I should really try this one out!#2022-09-2111:55eskosThis is great, and I’m not saying this just because I was one of the people who requested this. The not-so-great part is that this is one of those “why did I miss this obvious bug” things 😅#2022-09-2112:06lread@U8SFC8HLP I don't even ask that question anymore! simple_smile Just glad that clj-kondo, my ever-patient review buddy, helps me out. Thanks for requesting this feature.#2022-09-1922:06seepelWhen I have a line like this
(js/console.log "foo")
I get the following warning
Unresolved var: js/console.log
Is there any way to configure clj-kondo to handle these cases? I'm also curious if this syntax has a name that I would be able to google for.
#2022-09-2002:05skylizeThe js namespace is only provided by ClojureScript. So you need to either use a *.cljs file or use a`*.cljc` file with a cljs reader conditional.
;; if cljc file

(js/console.log "foo")          ;; unresolved

#?(:cljs (js/console.log "foo"))  ;; => "foo"
#2022-09-2002:22seepelIf I understand you correctly I don't think the js namespace is my problem. I am in a cljs file and the following lints fine
(.log js/console "foo")
I haven't changed my .clj-kondo/config.edn very much except to add a few :list-as rules, so I'm not sure what I might have mis-configured for this to lint properly
(js/console.log "foo")
#2022-09-2002:48skylize(.log js/console "foo") and (js/console.log "foo") should both be fine. You'll probably need to provide more info for help.#2022-09-2006:44borkdude(js/console.log "foo") is fine with clj-kondo, I do that all the time, but not when you're in a .clj or .cljc file#2022-09-2007:44borkdude@U03NXD9TGBD If you can post a repro with your problem (a full complete .cljwhatever file) then I'll be able to take a look. This shouldn't happen in .cljs file#2022-09-2202:15seepelSorry it took me a while to get back to you! I've been using clj-kondo only from vscode/vim so I wanted to make sure I installed the latest version and ran it directly. TLDR: I deleted .clj-kondo/.cache in my project and it seems to be working now? I don't get a warning for something like
(js/not.a.fn "foo)
but I could see how that might make sense. Is this the desired behaviour? Other symbols do give the warning, such as (foo 'bar) I installed on Ubuntu via the installation script https://github.com/clj-kondo/clj-kondo/blob/master/doc/install.md#installation-script-macos-and-linux Then I created a file src/test.cljs
(ns test)$ clj-kondo --lint src/test.cljs 
src/test.cljs:3:2: warning: Unresolved var: js/console.log
linting took 9ms, errors: 0, warnings: 1

(js/console.log "foo")
Running the linter produced the warning
$ clj-kondo --lint src/test.cljs 
src/test.cljs:3:2: warning: Unresolved var: js/console.log
linting took 9ms, errors: 0, warnings: 1
However, if I ran the same command outside of my project it did not produce the warning. This led me to believe it was a problem with my project, so I cleared the cache. Sorry I didn't have the foresight to save the cache before I deleted so I guess there is no way to debug now... :face_palm:
#2022-09-2220:58Anders EknertI’m seeing this too, with or without cache#2022-09-2220:58Anders Eknert
(ns main
  #?(:cljs (:require [cljs.nodejs :as node])))

(def ^:dynamic *env*
  #?(:clj (System/getenv)
     :cljs (if (= *target* "nodejs")
             (into {} (map #(vector % (aget node/process.env %)) (.keys js/Object node/process.env)))
             {})))

(defn env-var [name]
  (get *env* name))

(defn -main []
  (println (env-var "USER")))
#2022-09-2220:58Anders Eknert
clj-kondo --lint main.cljc
main.cljc:7:45: warning: Unresolved var: node/process.env
#2022-09-2220:59Anders Eknertcode compiles/runs fine though#2022-09-2221:07borkdude@U03AU2X8TD5 This is a different issue. In a .cljc file clj-kondo also lints the file as if it's a clj file. And in clj you can't write node/process.env#2022-09-2221:08borkdudeah wait, this is in a :cljs branch#2022-09-2221:08Anders Eknertindeed#2022-09-2221:08borkdudeTry (.-env node/process)#2022-09-2221:09borkdudeBtw, in Node you can also just write it like:
js/process.env
#2022-09-2221:10borkdudebut this seems like a genuine bug, so issue welcome#2022-09-2221:10Anders Eknert> Try (.-env node/process) yes. that works.. I was just saying that I too have had problems with the construct reported above#2022-09-2221:11Anders Eknertcool, I’ll file one before bedtime then 🙂#2022-09-1922:50seancorfieldWrote my first hook today! Debugged it via the REPL per the docs. Thank you @borkdude for a great, extensible tool (and great docs!) gratitude#2022-09-2008:02borkdudeThanks for sharing, it's always nice to get feedback like this#2022-09-2014:05Benjaminfoo.cljc
(ns foo)
(spit nil nil)

[
what about clojure.core functions in cljc files?
#2022-09-2014:06borkdudeit's unresolved because clj-kondo by default assumes clj + cljs in a .cljc file#2022-09-2014:06Benjaminyea ok I see#2022-09-2014:06borkdudeif you intend to write e.g. for bb, then you can use {:cljc {:features [:clj]}} to disable linting for cljs#2022-09-2014:06Benjaminah totally nice#2022-09-2015:21Noah BogartIf we're sharing about hooks, I'm up to 5! keep finding places where adding one instead of relying on :lint-as makes development better#2022-09-2016:13seancorfieldYeah, I have a bunch of :lint-as settings that I keep squinting at and thinking "Hmm, maybe that should be a hook". I definitely have another macro I'm going to write a hook for (although the red squigglies today are some encouragement to stop using it 🙂 )#2022-09-2016:25borkdudeFor anyone wanting to get more up to speed with hooks, you can do a self-paced "Getting hooked on clj-kondo hooks" workshop here: https://github.com/clj-kondo/hooks-workshop-clojured-2022#2022-09-2016:28borkdudeIf anyone wants to give that workshop at their company or a conference, feel free#2022-09-2016:32borkdudeBtw, if writing :analyze-call hooks for a macro is a bit too much, there is now also the :macroexpand hook which gives less accurate locations for warnings, but still gets rid of false positives by more or less just copying the macro (and simplifying it)#2022-09-2016:50Benjamin
(ns org.sg.sheets-lambda.core)
why is this an unparsable ns form?
#2022-09-2016:52borkdude@benjamin.schwerdtner clj-kondo version?#2022-09-2016:52Benjamin
clj-kondo v2022.09.08
`
#2022-09-2016:53borkdudeCan't repro that#2022-09-2016:53dpsutton
❯ echo "(ns org.sg.sheets-lambda.core)" | clj-kondo --lint -
linting took 4ms, errors: 0, warnings: 0
#2022-09-2016:53borkdudePerhaps close your editor and open the file again#2022-09-2016:53dpsutton(i always forget how to get the minimal way to check stuff so posting here for @benjamin.schwerdtner)#2022-09-2016:53Benjaminah maybe there is more caching that .clj-kondo/cache?#2022-09-2016:54Benjaminyea this echo command is great. 0 warns for me too#2022-09-2016:54Benjaminalso have it when I invoke with --lint manually#2022-09-2016:56borkdudeClose and reopen your editor#2022-09-2017:02Benjamin
(ns foo)

(comment
  (require '[lol oh-no :as]))
minimal repro. Lol when there is a garbled require form I guess anywhere in the file. Quality of life issue is that it logs the warning on the top ns form... Maybe the warning could at least mention that require elsewhere in the file can be an issue
#2022-09-2017:52borkdude@benjamin.schwerdtner Ah I see. Feel free to post an issue#2022-09-2017:57Benjaminok https://github.com/clj-kondo/clj-kondo/issues/1817#2022-09-2107:04Adam HelinsHey 👋 I must have changed something in my env but no idea what! In all Clojure files, Neovim now shows a warning about the namespace not matching the file name. I tried reinstalling Clj-kondo, purging the cache, ... can't seem to find the cure. This is purely an editor problem. Linting from the terminal doesn't output any warnings.#2022-09-2107:05borkdudeVersion and repro?#2022-09-2107:06Adam HelinsLatest v2022.09.08 Impossible to repro I'm afraid 😅#2022-09-2107:06borkdudePerhaps @U7ERLH6JX could also check as he is also using nvim#2022-09-2107:07borkdudeAs a workaround you can disable that linter for now #2022-09-2107:08Adam HelinsIt must be an env thing because I didn't update Clj-kondo meanwhile. At first I thought it was maybe somehow due to installing clojure-lsp but uninstalling it didn't help neither.#2022-09-2107:39Adam HelinsEven tried re-installing nvim... baffles me!#2022-09-2107:40borkdude@UCFG3SDFV I think I know what it is#2022-09-2107:40borkdudeyour nvim plugin likely lints via a temporary file or so and doesn't pass --filename#2022-09-2107:41borkdudeso then clj-kondo thinks the filename is entirely different from your real file#2022-09-2107:41borkdudeThe plugin should do something like this: https://github.com/borkdude/flycheck-clj-kondo/blob/ff7bed2315755cfe02ef471edf522e27b78cd5ca/flycheck-clj-kondo.el#L67#2022-09-2107:42lispycloudsWhat’s your linting setup @UCFG3SDFV ? You use something like null ls or nvim lint?#2022-09-2107:43Adam HelinsI've always been using Ale exactly like so: https://github.com/clj-kondo/clj-kondo/blob/master/doc/editor-integration.md#ale#2022-09-2107:43lispycloudsOn a side note, simply using lsp and clojure-lsp works for me for any file, don’t have a need for calling clj-kondo directly #2022-09-2107:44borkdudecheck the ale implementation#2022-09-2107:44lispycloudsProbably an issue in ALE. Trying to take a look#2022-09-2107:45Adam HelinsI did try re-installing the plugin. I sense installing clojure-lsp must have triggered some interference?#2022-09-2107:46Adam Helins(although it is removed now)#2022-09-2107:46lispycloudsIf you have both lsp and clj kondo they could interfere I guess#2022-09-2107:48borkdudeI run both in emacs#2022-09-2107:48borkdudebut I've disabled diagnostics from clojure-lsp an purely rely on the installed clj-kondo#2022-09-2107:48borkdudesince I usually have a local development version#2022-09-2107:50lispycloudsMakes sense.#2022-09-2107:51lispyclouds@UCFG3SDFV do you still have the same error running with just lsp?#2022-09-2107:51Adam HelinsIn any case lsp is now uninstalled, I purged the neovim/nvim-lspconfig plugin, re-installed Ale, and still the same 😕#2022-09-2107:52Adam Helins(I'm afraid to reinstall lsp now)#2022-09-2107:52borkdudeI don't see --filename here, that is likely the issue: https://github.com/dense-analysis/ale/blob/9b5a3581ebb7e6e1ccb0cbaeef5358aee57d734e/ale_linters/clojure/clj_kondo.vim#2022-09-2107:52lispycloudsYeah that’s what I was gonna say#2022-09-2107:52Adam HelinsBut why was it working perfectly fine before?!#2022-09-2107:54borkdudeBecause the namespace linter is a recent (few months ago) addition probably?#2022-09-2107:54borkdudeAnd I don't know for sure if this is the issue#2022-09-2107:54borkdudeI also don't know if ale uses a temp file or not#2022-09-2107:54borkdudecould be#2022-09-2107:55borkdudeflycheck has a flycheck-compile command which you can use to diagnose#2022-09-2107:55borkdudeperhaps ale has a similar thing#2022-09-2107:57lispycloudsim not using ALE for quite a while now, quite hard to debug too#2022-09-2107:57lispycloudshow about https://github.com/dense-analysis/ale/issues/3412 ?#2022-09-2107:57lispycloudsbut its quite old too#2022-09-2107:58lispycloudsalso https://github.com/dense-analysis/ale/pull/4109#2022-09-2107:58lispycloudsyeah i think this is the issue ^#2022-09-2107:59lispycloudsthis PR being unmerged is whats keeping it from working as expected#2022-09-2107:59borkdudehttps://github.com/dense-analysis/ale/pull/4109#issuecomment-1253344239#2022-09-2108:00Adam Helins@U04V15CAJ I guess you must be right, that looks like a very plausible explanation and maybe I wasn't as up-to-date as I thought#2022-09-2108:03lispyclouds@UCFG3SDFV maybe the workaround could be not using the ALE for clojure and using lsp? not sure when they could address the issue in ALE.#2022-09-2108:03borkdudeor just disable the namespace linter#2022-09-2108:03borkdudeI think it would be good to have ale work correctly#2022-09-2108:03borkdudesince many people use it#2022-09-2108:06Adam Helins@U7ERLH6JX Yes, I thought the issue might have been caused by lsp but it turns out it's the opposite (ale) Thanks to both of you, that was really helpful!#2022-09-2113:52lispyclouds@UCFG3SDFV just to close this off, https://github.com/mfussenegger/nvim-lint/blob/master/lua/lint/linters/clj-kondo.lua#L16 is how it should work. this is the bit i contributed to the plugin too and then switching to just using lsp :rolling_on_the_floor_laughing:#2022-09-2114:12Adam HelinsWell I followed your path eventually and everything is perfect now!#2022-09-2115:04lispycloudsnice! just as a side note, if its not too much work to move and since youre on nvim, i could recommend using https://github.com/mfussenegger/nvim-lint or https://github.com/jose-elias-alvarez/null-ls.nvim if you need something more than what the lsp can do. they are easier to debug and augment the built-in lsp mechanism nvim has, working with nvim-lspconfig#2022-09-2311:13opqdonutI see there's a nice helix clj-kondo config at https://github.com/lilactown/helix/tree/master/resources/clj-kondo.exports/lilactown/helix According to git tags that file is included in 0.1.7. However clj-kondo --dependencies --copy-configs doesn't find it for me. Does it work for anyone else? I guess I can always manually import it.#2022-09-2311:16opqdonutI do have a .clj-kondo dir and clj-kondo has managed to put other configs there.#2022-09-2311:16borkdudeCan you check if the dependency contains those files?#2022-09-2311:17borkdudeyou can e.g. do this with ls_jar: https://github.com/borkdude/tools#ls_jar#2022-09-2311:17borkdudeor jar -tf#2022-09-2311:17opqdonut
% zipinfo ~/.m2/repository/lilactown/helix/0.1.7/helix-0.1.7.jar| grep kondo
-rw----     2.0 fat        0 bl defN 22-Mar-29 21:15 clj-kondo.exports/
-rw----     2.0 fat        0 bl defN 22-Mar-29 21:15 clj-kondo.exports/lilactown/
-rw----     2.0 fat        0 bl defN 22-Jul-29 17:12 clj-kondo.exports/lilactown/helix/
-rw----     2.0 fat    10661 bl defN 22-Jul-29 17:12 clj-kondo.exports/lilactown/helix/config.edn
-rw----     2.0 fat        0 bl defN 22-May-12 20:52 clj-kondo.exports/lilactown/helix/clj_kondo/
-rw----     2.0 fat        0 bl defN 22-Aug-11 17:28 clj-kondo.exports/lilactown/helix/clj_kondo/lilactown/
-rw----     2.0 fat     3566 bl defN 22-Aug-11 17:28 clj-kondo.exports/lilactown/helix/clj_kondo/lilactown/helix.clj
#2022-09-2311:17borkdudethat looks ok#2022-09-2311:17opqdonutI even tried adding the helix-dep to my main :deps, but it didn't help. Previously it was only under my :shadow-cljs alias.#2022-09-2311:18borkdudeyou need to add --lint $(clojure -Spath)#2022-09-2311:18borkdudedid you have that? this wasn't clear from your OP#2022-09-2311:19opqdonutnow it worked#2022-09-2311:19opqdonut
% clj -M:clj-kondo --dependencies --copy-configs --lint $(clojure -Spath)
Configs copied:
- .clj-kondo/com.github.seancorfield/next.jdbc
- .clj-kondo/lilactown/helix
- .clj-kondo/metosin/malli
#2022-09-2311:20opqdonutI thought --dependencies --copy-configs would do the right thing on its own. I guess I should reread the docs.#2022-09-2311:21opqdonutthanks!#2022-09-2311:21borkdudeah yes, you always need to specify the classpath to clj-kondo explicitly, there is absolutely no magic with deps.edn detection etc :)#2022-09-2311:21opqdonutI get it now, yeah, kondo doesn't read my deps.edn#2022-09-2311:22opqdonutThat makes perfect sense#2022-09-2520:43borkdude@blak3mill3r The home config is in ~/.config/clj-kondo/config.edn but you probably found this out? :)#2022-09-2520:44blak3mill3rNo, the flycheck warning is from lsp#2022-09-2520:44blak3mill3rnot from clj-kondo directly#2022-09-2520:45blak3mill3roh, but that is good to know, thanks#2022-09-2520:46blak3mill3rokay, I moved my home config to the right location#2022-09-2520:46blak3mill3rbut still seeing Unresolved symbol everywhere for specter navigators like MAP-KEYS#2022-09-2520:47blak3mill3rflycheck-list-errors buffer shows it as Unresolved symbol: MAP-KEYS (lsp)#2022-09-2520:47blak3mill3rwhich means it is coming from clojure-lsp , which defers to clj-kondo IIUC#2022-09-2520:47blak3mill3rit should still respect my kondo config though... right?#2022-09-2520:48borkdude👋#2022-09-2520:48borkdudeyes, clojure-lsp uses clj-kondo#2022-09-2520:53borkdudewhat is your config?#2022-09-2520:54borkdudewhat might be the case is that you need to restart lsp after configuring this:
{:lint-as {com.rpl.specter/defcollector clojure.core/defn
           com.rpl.specter/defdynamicnav clojure.core/defn
           com.rpl.specter/defmacroalias clojure.core/def
           com.rpl.specter/defnav clojure.core/defn
           com.rpl.specter/defrichnav clojure.core/defn}}
#2022-09-2520:54borkdudesince clojure-lsp probably doesn't notice changes in the home config. also you might need to remove .lsp/.cache in your project#2022-09-2520:54borkdudeand then restart. cc @ericdallo#2022-09-2520:55ericdalloThis is already working on nightly builds #clojure-lsp-builds, soon we should do a clojure-lsp release including that :)#2022-09-2520:56borkdudeyay!#2022-09-2520:57ericdalloOh I didn't considered the home clj-kondo config only the project one 😅 , @U04V15CAJ is there a clj-kondo function where I can get all possible paths kondo consider as config?#2022-09-2520:57ericdalloI'm doing ATM: (io/file project-root-filename ".clj-kondo" "config.edn")#2022-09-2520:58borkdude@ericdallo there is a function in clj-kondo which gives you the entire config hash right?#2022-09-2520:58borkdudelemme check what that was again#2022-09-2520:58ericdalloyeah, I think we can just compare hashs so#2022-09-2520:59ericdalloit's just that I'm checking during the didSave if the URI was a lsp config file or clj-kondo one#2022-09-2521:00ericdallootherwise I'd need to check for kondo hash on every didSave which sounds a little bit slower#2022-09-2521:00borkdudeSo this function gives the entire configuration: https://github.com/clj-kondo/clj-kondo/blob/b501bf5c1c5884fc4b1fb6ba05eeedc7b0b5a148/src/clj_kondo/core.clj#L252 And you can put that into core/config-hash to get a hash back#2022-09-2521:00blak3mill3rHey, much obliged! Now I will enjoy clojure-lsp#2022-09-2521:00ericdalloyeah we already use that function on other places#2022-09-2521:00blak3mill3rkilling clojure-lsp and nuking the cache fixed it#2022-09-2521:01borkdudeAwesome :) Which editor are you using?#2022-09-2521:01blak3mill3remacs#2022-09-2521:02borkdudeThere are some (possibly minor) problems with emacs and clojure-lsp at the moment, which you may experience as short pauses in typing, but not everyone experiences this. If you do, please let us know.#2022-09-2521:03borkdudeYou can restart clojure-lsp from emacs with lsp-workspace-restart#2022-09-2521:20ericdalloAny intentions to make :unused-value enabled as default or there is some corner case where that might be false-positive?#2022-09-2521:24borkdude@ericdallo I'm a bit terrified of breaking people's builds by enabling new linters that have just been written#2022-09-2521:25borkdudeSo I'll probably let it be disabled for a couple of months and then enable it#2022-09-2521:25borkdudewhile I'm using it locally all the time#2022-09-2522:34dpsuttonIt would be cool if there was a flag that could be passed that would turn on all of the soon-to-be-default linters to help people easily adjust at their own pace before they get switched on#2022-09-2602:01Noah BogartMakes sense to be cautious. Do people upgrade the clj-kondo in their CI without first checking? That seems dangerous to me#2022-09-2602:30lreadI’m a bit on the extreme side and run it a specific version from the JVM for CI via a deps.edn dep#2022-09-2602:40lreadBut also excitedly try out each new version!#2022-09-2613:02ericdalloClojure-lsp bumps clj-kondo all the time, which affects lint as well#2022-09-2613:55Noah Bogartah yeah, clojure-lsp is a good point, that does keep up pretty actively.#2022-09-2614:38lreadYeah I appreciate all the up-to-date goodness that clojure-lsp brings to me in my editor. For CI, I want repeatability.#2022-09-2608:41borkdude@dpsutton Do you mean something like :experimental true and then after a while the experimental linters become default linters?#2022-09-2612:27skylize> soon-to-be-default linters "Experimental" sounds to me like ... well, experimental. I would have no expectations of a linter described as experimental even being complete, much less destined to be a default. I think the request is more like :planned-defaults true, to get an early jump on linters that you definitely hope to enable for everyone after some battle-testing. (Also gives people a heads up on such plans, so they can chime in with possible reasons to never default some particular linter.)#2022-09-2612:30borkdudeMeh, I think it might be sufficient to just keep future linters all optional and if people want to use them, they can do that#2022-09-2611:51robert-stuttafordshadow-cljs and kaocha both use the concept of a file-system watcher to trigger build and test runs. is it possible to run clj-kondo in this manner, so as to benefit from running it as a warm process? duh, of course it's possible. what i meant is, is anyone doing it and can i have your code please? 😅 why i am asking: i want to run kaocha, shadow and kondo-in-watch-mode all at the same time as i move a whole bunch of namespaces around. this way, i can watch one set of terminals and see all the feedback together, without having to browse files in my editor#2022-09-2611:52borkdudeyou can write a bb script which watches your sources and runs clj-kondo#2022-09-2611:52borkdudeyou can use the watcher pod from here: https://github.com/babashka/pod-babashka-fswatcher#2022-09-2611:53robert-stuttafordhah! we already have one. so all i need is to add the watcher. simple! thanks @borkdude#2022-09-2612:31robert-stuttafordhow i force a bb script to stay running?#2022-09-2612:32borkdude@robert-stuttaford @(promise)#2022-09-2612:33borkdudeThe promise that never gets delivered :)#2022-09-2612:33robert-stuttafordah darn of course!#2022-09-2612:34robert-stuttafordgot it working thanks @borkdude!#2022-09-2612:37borkdudeFeel free to add something to the clj-kondo wiki: https://github.com/clj-kondo/clj-kondo/wiki#2022-09-2613:27robert-stuttafordooh for sure!#2022-09-2616:08robert-stuttafordhttps://twitter.com/RobStuttaford/status/1574430197079752706 (is it ok for me to paste a link to a tweet like this?)#2022-09-2616:14borkdudeSure. It might have been nice to show the code in a different buffers so you don't get the clj-kondo lint warnings 🙈#2022-09-2616:32borkdudeAn animated gif might be even more awesome where you can see you can navigate :-D#2022-09-2617:07robert-stuttafordhaha i haven't unlocked the make a gif achievement yet 😄#2022-09-2617:37borkdudeTry Cmd-shift-5 in macOS or download licecap :)#2022-09-2617:40robert-stuttafordlicecap 😍#2022-09-2620:32snoe@borkdude would it be worth shipping kondo with these hooks? datomic and malli are at least as popular as re-frame.#2022-09-2620:35borkdudeI'd rather not ship any built-in stuff if it can be done in libraries. In the beginning it was a necessity but this is no longer true#2022-09-2620:36borkdudeI've had a lot of churn in the re-frame stuff with edge cases which led to releasing new versions of clj-kondo, which is not a problem you have when you do it in libs#2022-09-2620:40snoeoh right, so a PR for the hook could be added to malli and --copy-configs used in projects that depend on it. In theory, the same should be done for re-frame#2022-09-2620:42borkdudeexactly, but we already had re-frame built-in#2022-09-2620:47snoeso @robert-stuttaford that could be a way to contribute to the ecosystem if you're interested.#2022-09-2620:52borkdudegood luck contributing to datomic tho :)#2022-09-2620:53snoeyeah 😞.would clj-kondo/config be usable as a contrib for uncooperative libraries?#2022-09-2620:55borkdudeyeah, I am considering chopping up clj-kondo/config into multiple libraries, so you can just include extra libraries on your classpath to get configs#2022-09-2618:45Noah Bogarti'd like to ensure that every test file requires a specific test setup file that does some side-effecting set up. i could do this in a hook, i think, but would there be any interest in adding this as an official linter rule?#2022-09-2619:22Noah Bogart~it seems that ~#2022-09-2619:27borkdudeclj-kondo doesn't really distinguish between your code and dependency code. hooks are always executed#2022-09-2619:28Noah BogartI must have an error in my code then, thanks#2022-09-2620:39Noah Bogartah, it was a caching issue. I should have checked that first. Thanks#2022-09-2814:28souenzzoclj-kondo do not have warns to tagged-literals like #uuid id it could report uuid tagged literal expect an string for clojure.core taggeds, it could also report things like "xxx" is not a valid uuid https://ask.clojure.org/index.php/12256/improve-syntax-errors-on-tagged-literals#2022-09-2814:47borkdudeSure#2022-09-2814:49borkdude@souenzzo Issue welcome#2022-09-2900:36vemv:discouraged-var rocks! I give it a couple creative usages: 1) fostering an abstraction (vs. a rawer naive approach). Sooner or later every codebase needs this. 2) avoiding functions that aren't dangerous per se, but happen to be incorrect in a certain context (in my case spit - I often spit in the middle of a deftest to update my expectation that is a resource )#2022-09-2907:37robert-stuttafordcarve finds unused vars, as does lsp (if you visit the file and see the annotation). how does one list all the namespaces that haven't been required?#2022-09-2907:52borkdudetakes long drag on joint @robert-stuttaford it's just data dude_:_ https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#2022-09-2907:53borkdude(freely after https://twitter.com/plexus/status/1381917693247434754)#2022-09-2907:59robert-stuttafordi guess i have to learn clj-kondo analysis don't i 😆#2022-09-2908:00borkdude@robert-stuttaford there are some examples at the end of the document#2022-09-2908:00borkdudeit's basically: collect all defined namespaces and subtract all used namespaces#2022-09-2908:01robert-stuttafordthank you sir!#2022-09-2908:26robert-stuttafordlol 82mb edn file. not editing THAT with emacs#2022-09-2908:33robert-stuttafordnice, got it:
;; clj-kondo --lint dev src test --config '{:output {:format :edn}, :analysis true :var-usages false :var-definitions {:shallow true}}' | jet --func '#(-> % :analysis (select-keys [:namespace-definitions :namespace-usages]))' > kondo.edn

  (def ka (-> "kondo.edn" slurp edn/read-string))

  (set/difference (into (sorted-set) (map :name) (:namespace-definitions ka))
                  (into (sorted-set) (comp (map :to) (remove string?)) (:namespace-usages ka)))
#2022-09-2919:45borkdudeAwesome#2022-10-0509:46souenzzoSometimes I create a test namespace where I import kondo and do a few assertions about analisys, to ensure project wide things.#2022-09-2915:03Noah BogartI've run into an oddity I didn't expect. unused-binding {:exclude-destructured-as true} warns on vector :as bindings#2022-09-2915:04Noah Bogart
$ echo '(let [{a :a :as b} {:a 2} [c :as d] (range 2)] (prn [a c]))' | clj-kondo --config '{:linters {:unused-binding {:level :error :exclude-destructured-as true}}}' --lint -
<stdin>:1:34: error: unused binding d
linting took 5ms, errors: 1, warnings: 0
#2022-09-2915:18borkdudeIssue welcome #2022-09-2916:16Noah Bogarthttps://github.com/clj-kondo/clj-kondo/issues/1821 and https://github.com/clj-kondo/clj-kondo/pull/1822#2022-09-2916:12lilactownI'm trying to look for ways to speed up analysis of a very large codebase. currently, analysis takes ~90s on my fancy m1 MBP. what i've tried so far: • skip linting • parallel true • skipping var definitions here's how i'm running the analysis
(kondo/run!
 {:lint src-files
  :parallel true
  :skip-lint true
  :config {:output {:analysis {:var-definitions false}}}})
I do need var usages. However, I only need var usages of specific namespaces. Is it possible to speed up analysis by customizing what data it actually looks for? I was previously doing this with grasp, where each ns I was looking for took ~30s to find all usages. clj-kondo scales much better than this obviously, but I'm writing a tool that people might use at the CLI, so I want it to be as fast as possible.
#2022-09-2916:12lilactownfor reference, it's about 4500 clojure files it's analyzing. so i'm not like, appalled at the perf here. just want to make it better 😄#2022-09-2916:17Noah Bogart4500 files??? 👀#2022-09-2916:20lilactownclose
$ find . -type f -name '*.clj' | wc -l
3534
$ find . -type f -name '*.cljs' | wc -l
668
$ find . -type f -name '*.cljc' | wc -l
306
#2022-09-2918:50borkdude@U4YGF4NGM There could be a faster way, possibly, but with more false positives#2022-09-2918:50borkdudeSo if you're interested in inaccurate results with better performance, I'm sure that can be done, but so far the tools that use clj-kondo don't want inaccurate results#2022-09-2919:38borkdude@U4YGF4NGM Another thought: have you tried tools.analyzer? Not sure what the performance of that is for this use case, could be better or worse. Curious#2022-09-2920:08lilactownl havent tried tools.analyzer#2022-09-2920:08lilactowni do want accuracy#2022-09-2922:08lilactownI wonder if we could the analysis along with the linting info?#2022-09-3006:42borkdudeThis is already the case: :findings and :analysis #2022-09-3015:37lilactownif I have a script that runs clj-kondo, can I ensure that it stores and uses the cache? it doesn't seem to be#2022-09-3015:37lilactowneach run of the script re-analyzes the repo (taking 90+ seconds), destroying my brain 🧠#2022-09-3015:38borkdude@U4YGF4NGM This requires the existence of a .clj-kondo directory or an explicit :cache argument. The cache is only read for information from other namespace, it doesn't skip analysis for things it has already seen before (as it might have changed)#2022-09-3015:38lilactownah ok#2022-09-3015:39borkdudeAre you linting any .jar files?#2022-09-3015:39lilactowni'm not trying to, but there are probably jars on disk#2022-09-3015:40borkdudeit might be good to do some caching yourself: skip linting this and that file / dir if you don't have any changes#2022-09-3015:40borkdudeclj-kondo doesn't contain a lot of magic, it just analyzes/lints whatever you throw at it#2022-09-3015:42lilactownyeah, was wondering of kondo might already handle that for me#2022-09-3015:43lilactownultimately it doesn't matter so much, this is going to run in CI for the most part where if it takes a few minutes it's ok. just the development loop sucks 😄#2022-09-3015:43lilactowntrying to solve MY problem not THE problem rn#2022-09-3015:44borkdudeI would say: save your analysis on disk under a content hash and content hash the analyzed file too#2022-09-3015:44borkdudeand then it becomes obvious what to skip#2022-09-3015:46borkdudeor work with a smaller input in dev#2022-09-3022:55lilactownthis isn't really a question about clj-kondo, but I'm trying to use native-image to compile my project that uses clj-kondo for analysis, and it's failing to compile. I've narrowed it down to my call to clj-kondo.core/run!. I get the following error:
Fatal error: java.lang.NullPointerException
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.image.LIRNativeImageCodeCache.addDirectCallTrampolines(LIRNativeImageCodeCache.java:280)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.image.LIRNativeImageCodeCache.layoutMethods(LIRNativeImageCodeCache.java:178)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:645)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:521)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:407)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:585)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:128)
--------------------------------------------------------------------------------------------------------------------
                      7.8s (11.2% of total time) in 35 GCs | Peak RSS: 4.04GB | CPU load: 4.89
====================================================================================================================
Failed generating 'mulch' after 1m 9s.
Error: Image build request failed with exit status 1
com.oracle.svm.driver.NativeImage$NativeImageError: Image build request failed with exit status 1
	at com.oracle.svm.driver.NativeImage.showError(NativeImage.java:1716)
	at com.oracle.svm.driver.NativeImage.build(NativeImage.java:1413)
	at com.oracle.svm.driver.NativeImage.performBuild(NativeImage.java:1374)
	at com.oracle.svm.driver.NativeImage.main(NativeImage.java:1361)
#2022-09-3022:55lilactownthis is using graalvm-ce-java11-22.2.0#2022-09-3023:19lilactownI was able to fix this by setting JAVA_HOME=$GRAALVM_HOME when compiling my main namespace #2022-10-0106:59Matthew Davidson (kingmob)Maybe a silly question, but is :lint-as meant to be transitive? E.g., if I have in the lint-as map:
{outside.lib/foo clojure.core/def
 outside.lib/bar outside.lib/foo}
and I use outside.lib/bar, shouldn’t clj-kondo be able to ultimately resolve outside.lib/bar as clojure.core/def?
#2022-10-0107:04borkdudeIt’s currently not transitive #2022-10-0107:06Matthew Davidson (kingmob)ahh, ok#2022-10-0107:07Matthew Davidson (kingmob)What about if a hook existed instead for outside.lib/foo ?#2022-10-0107:20borkdudeThat might work
#2022-10-0107:20Matthew Davidson (kingmob):thinking_face:#2022-10-0107:23borkdudeI’d have to look it up, but afk. You could test it out #2022-10-0107:24Matthew Davidson (kingmob)It’s not a lot of work to fix, I was just surprised that wasn’t already how kondo worked#2022-10-0108:30Matthew Davidson (kingmob)Is there a config scenario where .clj-kondo/config.edn is ignored, or the config-paths entry inside it is? I’ve been tearing my hair out trying to figure out why my changes to resources/clj-kondo.exports/potemkin/potemkin/config.edn weren’t getting picked up. In desperation, I copied the same config lines to .clj-kondo/config.edn , and lo and behold, it worked. I had what I thought was a valid config paths entry: :config-paths ["../resources/clj-kondo.exports/potemkin/potemkin/"], but it didn’t seem to have any effect. I also had an older config.edn in .clj-kondo/potemkin/potemkin/config.edn (iirc), and deleting it seemed to fix the situation, but I haven’t found anything in the docs to explain what was going on.#2022-10-0108:48borkdudeMaybe try deleting the trailing slash. I am afk today but will look later tonight#2022-10-0108:50Matthew Davidson (kingmob)I tried with and without the slash earlier, and it didn’t seem to make a difference, but I’ll double-check#2022-10-0108:51Matthew Davidson (kingmob)Thanks for all your help, btw#2022-10-0109:01borkdude Normally what you had with ../resources without the trailing slash should work#2022-10-0109:02borkdudeThere are various other examples of this in a clj-Kondo issue #2022-10-0109:02borkdudeWhich I can’t link to because phone #2022-10-0109:02Matthew Davidson (kingmob)I tried again, and found no difference. FWIW, it seems to be working now, once I removed .clj-kondo/potemkin/potemkin/config.edn#2022-10-0109:03borkdudeMakes sense#2022-10-0109:05Matthew Davidson (kingmob)Now I’m trying to figure out why kondo is finding potemkin.namespaces/ in the top-level potemkin, but *not anything else…when it seems like it shouldn’t find anything…not that that’s helpful for potemkin consumers, but I’m a bit confused#2022-10-0110:25Matthew Davidson (kingmob)…really doubting whether linting many of the potemkin types is worth it.#2022-10-0110:33borkdudeClj-kondo has built-in support for the most frequently used thing in Potemkin: import-vars#2022-10-0110:35Matthew Davidson (kingmob)Yeah. I was most interested in supporting Aleph’s usage, but it looks like handling stuff like def-abstract-type and def-map-type will be seriously nontrivial. If Potemkin had more use, I might slog thru, but it’s getting really hard to justify the more esoteric uses. #2022-10-0110:36borkdudeYeah agreed. You could just use def-catch-all for those #2022-10-0110:37Matthew Davidson (kingmob) How does def-catch-all compare to deftype, which several of these bottom out at?#2022-10-0110:40borkdudeIt only registers the var and ignores everything else #2022-10-0110:42Matthew Davidson (kingmob)Got it. Still, that might be preferable for things like def-map-type, which keeps causing “Invalid arity” warnings, because it thinks the assoc definition is a call to clojure.core/assoc…let me try that out…#2022-10-0110:44Matthew Davidson (kingmob)Michiel, thanks for all your help. I think I’ll try to cut a release for some very basic kondo support for potemkin, and then set it aside#2022-10-0320:43borkdudeI'm aiming for a new release on Wednesday. If you can, take a look at these changelogs and try out the master version: https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#unreleased There are a couple new interesting linters in there.#2022-10-0320:53Noah Bogartwhat's the best way to run master as my primary "clj-kondo"?#2022-10-0320:54borkdude@UEENNMX0T do you mean, in your editor or in CI / command line?#2022-10-0320:56Noah Bogartcommand line, as that's simplest and I rely on clj-kondo bundled with clojure-lsp in my editor#2022-10-0320:57borkdudeI run clj-kondo separately from clojure-lsp in my editor so I can always run the latest (this is especially convenient when developing clj-kondo)#2022-10-0320:57borkdudeto get the master version, you could just download it from CI#2022-10-0320:57borkdudeor build it yourself#2022-10-0321:00borkdudelet me know if you have any questions about this#2022-10-0321:02Noah BogartI forgot that CI builds the artifacts, so I've downloaded one#2022-10-0321:05Noah BogartFound one thing, I'll thread it#2022-10-0321:05Noah Bogart
$ echo "(defn a ([b] (inc b)))" | ~/Downloads/clj-kondo-2022.09.09-SNAPSHOT-linux-static-amd64/clj-kondo --lint - --config '{}'
<stdin>:1:1: error: clojure.core/defn is called with 2 args but expects 3 or more
linting took 6ms, errors: 1, warnings: 0
#2022-10-0321:06borkdudeCould you submit an issue for that?#2022-10-0321:06borkdudeThanks for finding it#2022-10-0321:12Noah Bogarthttps://github.com/clj-kondo/clj-kondo/issues/1825#2022-10-0321:13borkdudeThis was already an issue with the previous release?#2022-10-0321:17Noah BogartYeah, it seems so. I ran it with master, then ran it with latest release. Doesn’t happen with 2022.08.03#2022-10-0321:18borkdudeok, good to know, thanks#2022-10-0415:08Noah Bogarti feel foolish, this was a cache issue. Looks like even tho I was relying on --config {}, i should have said --cache false to ensure a clean slate. Running this in other directories shows the error isn't happening.#2022-10-0415:21borkdudeok, so the issue can be closed?#2022-10-0415:21Noah BogartYeah, I closed the issue already, posted a similar message there#2022-10-0415:21borkdudeOne thing less for me to do tomorrow :)#2022-10-0323:28lilactownI'm trying to run a script I wrote in clojure that uses kondo's analysis in CI. I'm wondering if anyone has any tips for tuning it? I'm running into an issue where if I set the max heap size to 1g or under, I get the following:
{:clojure.main/message
 "Execution error (OutOfMemoryError) at clj-kondo.impl.core/format-vars$fn (core.clj:564).\nGC overhead limit exceeded\n",
 :clojure.main/triage
 {:clojure.error/class java.lang.OutOfMemoryError,
  :clojure.error/line 564,
  :clojure.error/cause "GC overhead limit exceeded",
  :clojure.error/symbol clj-kondo.impl.core/format-vars$fn,
  :clojure.error/source "core.clj",
  :clojure.error/phase :execution},
however if i set the heap higher, e.g. 2g, it gets killed by the host
=> Analyzing sources: ["/home/circleci/app"] ..../util/mulch.sh: line 5: 18171 Killed                  clojure -J-Xmx2g -Sdeps "$DEPS" -M util/mulch/main.clj "
#2022-10-0400:01lilactownthis is with :analysis true, which i'm guessing is what's generating all the memory#2022-10-0406:01borkdudeIt’s probably best to batch only 10 or 100 (variable, try) dirs or jars at a time#2022-10-0406:01borkdudeThis is what lsp also does #2022-10-0413:52lilactownmakes sense#2022-10-0409:12robert-stuttafordProbably a total non-issue and i'm just being pedantic, but i notice that some linter messages start with a capital letter, and some don't 🙂#2022-10-0409:13borkdudeYes, we moved from non-capital to capital and this is now the preferred style, but changing the old ones might break people's builds#2022-10-0409:13robert-stuttafordaha! no breaking changes or Rich will shuffle your stacktraces#2022-10-0415:37lilactownwhy would a map in :var-usages have nil for :row and :col?#2022-10-0415:39borkdude?#2022-10-0415:43lilactownI've got data like
{:name-end-col 17,
  :name-end-row 24,
  :name-row 24,
  :name a,
  :filename
  "...",
  :alias d,
  :from amperity.web.workflows.workflow.resolutions.plugin,
  :col nil,
  :name-col 14,
  :from-var credentials-page-link-component,
  :arity 3,
  :row nil,
  :to helix.dom}
#2022-10-0415:43lilactownin the analysis data#2022-10-0415:44lilactownit's not every usage, but a lot#2022-10-0415:45borkdudeThis might come from a hook which doesn't propagate location metadata#2022-10-0415:46lilactownah. we do have a few kondo hooks for helix#2022-10-0415:46lilactownis there an example of how to propagate location metadata?#2022-10-0415:47borkdudewhen generating the a call, you have to set metadata, e.g. from the outer node#2022-10-0415:47borkdudee.g. (with-meta (list-node ...) (meta node))#2022-10-0415:52snoeThat might be a useful warning for hook devs.#2022-10-0417:27sheluchinI came across this when running analysis on a bunch of libraries. It is a fairly common thing in the wild.#2022-10-0417:29borkdudeWhat clj-kondo could maybe do is remember the col / row of the parent and report that as a fallback#2022-10-0417:29borkdude(if there is a parent)#2022-10-0417:30sheluchinActually, I thought I did something to fix that in https://github.com/clj-kondo/clj-kondo/issues/1812#2022-10-0417:31borkdudeBut this isn't released yet. Perhaps @U4YGF4NGM can try with the master version. I hope to finish this release tomorrow#2022-10-0421:33lilactownjust tried what's in master f0935686f0c4e5690b0965189a7bb11f85b5510d and i still get nil for :row and :col for the same number of vars#2022-10-0421:45sheluchinAh, I'm afk right now so can't browse the rest of the kondo source but it looks like the tests I added were only for :var-definitions. I guess usages has a similar problem that was not fixed there.#2022-10-0421:46borkdudeI still suspect this to be a hook-specific problem#2022-10-0421:49sheluchinYeah, it's just many hooks out there currently have this problem. I guess it depends on the use case. If there can be some fallback added that provides better results without fixing every hook that omits meta, it would be nice.#2022-10-0421:56borkdudeIssue welcome#2022-10-0422:01sheluchinI can take a shot at a fix in a week or two if no one gets around to it by then.#2022-10-0504:50lilactownthis change seems to fix most of the issues for helix code https://github.com/lilactown/helix/commit/09a72365004ee788b8d3f74d7cb2fd4144a17f00#2022-10-0504:53lilactownI'm not sure how to add the line numbers back to the new-opts value#2022-10-0607:05borkdudeIssue still welcome#2022-10-0607:05borkdudein case we forget#2022-10-0620:22borkdudeI'm working on it already#2022-10-0621:20borkdude@UPWHQK562 By introducing the fix, I could also revert your change in PR 1813. Can you check if that makes sense? https://github.com/clj-kondo/clj-kondo/compare/fallback-location-for-hooks?w=1 @U4YGF4NGM Could you test with this branch / SHA of clj-kondo?#2022-10-0621:23borkdudeThat is: SHA 34b751fda59dc1f709f55f04554bbe329d4d4ac1#2022-10-0622:13sheluchin@U04V15CAJ traveling right now so can't do the most thorough review but it looks good. I wonder if you can also simplify the :name-row etc. fields so the logic a few lines below in reg-var! can be consistent.#2022-10-0622:14borkdudeok, I'll continue tomorrow#2022-10-0622:15sheluchinThe gist of it is you're moving the fallback logic to a more generic location and giving it the explicit name :fallback-loc?#2022-10-0707:09borkdudeYes#2022-10-0714:47borkdudeI looked at your other (or (:name-row ...) ...) stuff @UPWHQK562 but this was still necessary#2022-10-0715:27sheluchinAlright, it would have been nice to make it consistent but this is still a nice improvement. Thanks for working on this, @U04V15CAJ 🙏#2022-10-0719:34borkdudeok @U4YGF4NGM and @UPWHQK562 I merged the final solution to master now. I already had a similar solution for :macroexpand hooks but I now applied the same solution to :analyze-hook for nodes that don't have a location https://github.com/clj-kondo/clj-kondo/commit/17423d1b90498c4667663bd256056fd38bffc46c Please test#2022-10-0719:41borkdudee556f9c5f53620cc9acb2030257c1461556dab84 would be the best commit to test with#2022-10-0719:41borkdudeLet's say, just latest master commit#2022-10-0817:49sheluchin@U04V15CAJ Nice, that looks like a much more elegant overall solution. Looking forward to testing this out shortly.#2022-10-0417:53Darin Douglassis setting {:cljc {:features [:clj]}} still the proper way to lint a bb/clojure namespace?#2022-10-0417:53borkdudeyes#2022-10-0417:53Darin Douglassty ty#2022-10-0507:39JHi guys! I don’t understand why clj-kondo is disabled here (emacs). I follow the use-package installation. The flycheck-verify-setup give me this:#2022-10-0507:42borkdudeAnd if you do flycheck-select-checker?#2022-10-0508:32J#2022-10-0508:34borkdudeAnd have you tried doing what flycheck says at the bottom?#2022-10-0508:35JYes. I got No syntax checkers disabled in this buffer#2022-10-0509:11borkdudehave you tried restarting emacs?#2022-10-0509:31JYes#2022-10-0509:32JMy config for clj-kondo. (I have (setq use-package-always-ensure t))#2022-10-0509:33borkdudeWhat is the file extension of this buffer?#2022-10-0509:34JMy config is the init.el . All other screens are made on a .clj file.#2022-10-0509:36borkdudeWhat do you see when you run flycheck-compile#2022-10-0509:36borkdudein the buffer#2022-10-0509:50JSeems work#2022-10-0509:53JBut I don’t have warning in the buffer.#2022-10-0509:56borkdudeYeah, strange. I'm not really familiar with use-package, so perhaps try #emacs What you could also do is manually do (require 'flycheck-clj-kondo)#2022-10-0509:56borkdudeand perhaps flycheck-select-checker and then select clj-kondo#2022-10-0509:57borkdudeis it possible you are also using lsp-mode?#2022-10-0510:00JI not use lsp-mode . I will try your recommendation.#2022-10-0510:24JI don’t have clj-kondo in checkers but clj-kondo-clj , clj-kondo-cljs, etc... It’s ok?#2022-10-0510:24JI will ask to #emacs too.#2022-10-0510:25borkdudeyes, there is one checker for each file type#2022-10-0511:45borkdudeI'm on schedule for the planned release today: just one more issue... https://github.com/clj-kondo/clj-kondo/projects/1 (see high priority column)#2022-10-0515:20borkdudeCI is building 2022.10.05 now...#2022-10-0515:45borkdudeDone!#2022-10-0521:55Ella HoeppnerI've got a macro that takes in a list of symbols and returns a do expression containing a defonce for each those symbols. This causes red squiggles with an Unresolved symbol warning for those symbols both inside the call to the macro and everywhere else those symbols are referred to in the file. I can fix the warnings inside the macro call with def-catch-all, but that does nothing for the warnings in the rest of the file. Is there anything I can do to make this work?#2022-10-0522:00borkdudeHi! I think you could write a hook for this macro: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md A (hopefully) gentle introduction: https://github.com/clj-kondo/hooks-workshop-clojured-2022 tl;dr: the :macroexpand hook allows you to more or less copy your macro to your configuration and is probably the least amount of effort. The :analyze-call macro allows you to do more and with more accuracy but might be overkill for your macro which just defines vars.#2022-10-0522:02borkdudeIt's getting late here, but I'll check in tomorrow again.#2022-10-0607:12borkdudeHope you were able to get something going#2022-10-0616:55Ella Hoeppneryep, :macroexpand was exactly what I needed, thanks!#2022-10-0605:04robert-stuttafordplease may we also have the clj-kondo bb pod updated to 2022.10.05? 😌#2022-10-0607:05borkdudeDone!#2022-10-0607:06robert-stuttafordamazing thank you!#2022-10-0607:07robert-stuttafordfyi, we now bump both the jvm and bb pod at the same time, so there's a +1 to 'number of people needing coordinated releases' for your usage data 🙂#2022-10-0607:11borkdudeI should remember to do this when releasing clj-kondo#2022-10-0611:45robert-stuttafordthat's be lovely, yes please 😄#2022-10-0611:31andrewzhurov👋 is it possible to add #p as an discouraged var.. or rather reader macro?#2022-10-0611:32imreooh a fellow hashp user! 👋:skin-tone-3:#2022-10-0611:34borkdudecurrently not, but there is a :config-in-tag option which configures linting behavior in tags. Not sure if this will help in this case, probably not#2022-10-0611:46andrewzhurovloving #p a ton, but occasionally it slips into commits thanks for a prompt reply#2022-10-0612:23imreI know. My secret is that I never add it to the checked-in deps.edn, just keep it in my user-level one so in theory it should fail compilation#2022-10-0613:30Noah BogartHow does :redundant-fn-wrapper work? It seems like it only recognizes a predefined set of functions?
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "3f51505e577f5c5d125b5a5353"}, :content ("[email protected]")}
#2022-10-0613:45borkdudeI'm not exactly sure why this case isn't detected#2022-10-0613:53Noah Bogart
$ echo "(let [uuids [{:a 1}]] (map #(:a %) uuids))" | clj-kondo --lint - --config "{:linters {:redundant-fn-wrapper {:level :error}}}" --cache false
linting took 8ms, errors: 0, warnings: 0
also with keywords for some reason
#2022-10-0613:54borkdudeI'd have to look into how it works again, it's been a while#2022-10-0613:54borkdudeI also found that in some cases redundant-fn wrappers are still desirable, e.g. for hot reloading#2022-10-0613:54borkdudeSo I haven't enabled it anymore locally#2022-10-0617:40Noah Bogarthttps://github.com/clj-kondo/clj-kondo/pull/1832#2022-10-0618:23borkdudeThanks for the PR. I'm going to check if I can see some interesting new discoveries when I'm running the lint diff#2022-10-0618:24borkdudeSometimes you can discover cases that aren't working properly, so that would be good before merge#2022-10-0618:24Noah Bogartno rush! just something I noticed after cleaning up the existing lint warnings in our production codebase#2022-10-0618:28borkdude
< clojure/inspector.clj:120:17: warning: Redundant fn wrapper
3125d3123
< sci/impl/utils.cljc:204:38: warning: Redundant fn wrapper
3367c3365
#2022-10-0618:29borkdudenice: https://github.com/clojure/clojure/blob/5da21b38470d175b3cecbf93b9cd145ca36940c1/src/clj/clojure/inspector.clj#L120#2022-10-0618:30borkdudenice: https://github.com/babashka/sci/blob/2b987b90df613daedf321c0987d8e4d5fe2465c6/src/sci/impl/utils.cljc#L204#2022-10-0618:07Noah BogartI have a fix for :include-macros bug from github earlier today, but I see that we could be more strict about it than just passing over it. Clojurescript's https://github.com/clojure/clojurescript/blob/a4673b880756531ac5690f7b4721ad76c0810327/src/main/cljs/cljs/core/specs/alpha.cljc#L130 says it only accepts true. Should I convert this fix (that merely discards the form) to a new linter that checks to make sure the option is the literal true?#2022-10-0618:08borkdudeFine with me#2022-10-0618:08borkdudeAlso: cljs only#2022-10-0618:08Noah BogartRight, I'll include that#2022-10-0618:14Noah BogartIs that something you want to warn about or just skip if in clojure?#2022-10-0618:15Noah Bogartlooks like we're not doing such checks for other :require options#2022-10-0618:17borkdudein clojure this is not a valid option#2022-10-0618:17borkdudeso that's an unknown-require-option then#2022-10-0618:19borkdudePerhaps in a .cljc situation it's convenient to leave it in, if it also works for clojure#2022-10-0618:19Noah BogartI mean that :refer-macros is allowed in clojure, but we could lint it:
$ clj
Clojure 1.11.1
user=> (require '[clojure.string :refer-macros [join]])
nil
user=> (join " " (range 10))
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: join in this context
#2022-10-0618:19Noah Bogartyeah, clojure doesn't care#2022-10-0618:19borkdudeEverything is allowed right#2022-10-0620:45Noah Bogarthttps://github.com/clj-kondo/clj-kondo/pull/1834#2022-10-0620:45Noah BogartThis works but doesn't feel ideal so let me know how you want to go with it#2022-10-0621:15borkdudeTo me this feels way too much for simple syntax check, I wouldn't even introduce a new linter for this. Just a warning with type :syntax#2022-10-0621:15Noah BogartOh yeah, I completely forgot about that one. Thanks, I’ll clean it up#2022-10-0713:47Noah BogartUpdated, much simpler now. I included a change to make :unknown-require-option default to :off, which should help everyone out in general#2022-10-0710:41serioga@borkdude clj-kondo does not know about :include-macros require option (“Unknown require option: :include-macros”)? https://clojurescript.org/guides/ns-forms
(ns bar.core
  (:require [foo.core :as foo :include-macros true]))
should I file an issue?
#2022-10-0710:42borkdude@serioga Thank you. There is already an issue and PR for this, I will merge this soon#2022-10-0710:46serioga@borkdude will it be accepted in CLJ files too? Or I shoud use reader conditionals in CLJC files? At least Clojure compiler does not complain about this option.#2022-10-0710:47borkdude@serioga Good data point, thank you. If the Clojure compiler doesn't complain, then perhaps we should just let this slide inside a .cljc file#2022-10-0710:47borkdudecc @nbtheduke#2022-10-0711:00Noah BogartDoes clj-kondo know it’s in a cljc file? I thought it just ran twice, one for each dialect#2022-10-0711:00borkdudeYes, it knows, in the context we have :base-lang and :lang. :base-lang can be :cljc#2022-10-0711:01Noah BogartCool, I’ll check for that. Will be on my computer and fix the pr in an hour or two.#2022-10-0711:48serioga@nbtheduke Clojure does not complain about :include-macros in CLJ file too 🙂#2022-10-0712:00borkdudeClojure doesn't complain about anything, but the point of that linter is to prevent typos by adding options that don't do anything#2022-10-0712:00borkdudeIf you're not interested in that, just don't use the linter, it is disabled by default#2022-10-0713:22serioga@borkdude which linter is disabled by default? At the moment “clj-kondo v2022.10.05” warns me about :include-macros and I did not enable it AFAIK#2022-10-0713:24borkdude@serioga Really? Damn, that wasn't my intention#2022-10-0713:24serioga:-)#2022-10-0713:25borkdudeaw crap, this slipped through: https://github.com/clj-kondo/clj-kondo/blob/5eaa490efef7041c97d990620cca2403b2d18d81/src/clj_kondo/impl/config.clj#L39#2022-10-0713:25borkdudeHmm, I see... https://github.com/clj-kondo/clj-kondo/pull/1808#issuecomment-1246503198#2022-10-0713:26borkdudeI must have not been paying attention ;)#2022-10-0713:26seriogaSo will it be kept as is?#2022-10-0713:27borkdudeI think we should disable it by default#2022-10-0713:28borkdudeEspecially for the first few months#2022-10-0713:28borkdudeI do this for all new linters#2022-10-0713:29Noah BogartOops, also my bad. Sorry about all this#2022-10-0713:30serioga😄#2022-10-0713:30borkdudeNo problem, people can always use #_:clj-kondo/ignore I think but I don't want to disturb anyone's CI by upgrading blindly ;)#2022-10-0713:31seriogaAt least now I know how to switch it off :-)#2022-10-0713:47Noah BogartFix is up here: https://github.com/clj-kondo/clj-kondo/pull/1834#2022-10-0713:52borkdudeLGTM, barring a few minor comments#2022-10-0920:10borkdude@nbtheduke Now that we have the linter on in the current clj-kondo anyway, I've thought about it some more and maybe we should just leave it on, but I want to have an option to add options (for custom languages like clojuredart, or whatever is to come) to add options that should not be warned about, I think#2022-10-0920:11Noah BogartHow do you want it to look? #2022-10-0920:11borkdudeProbably :exclude [:import-foobars]#2022-10-0710:42borkdude@nbtheduke Perhaps we should also add an option to this so people can exclude certain options in user space#2022-10-0710:42seriogaoops, I see a message above 😳#2022-10-0710:46serioga@borkdude will it be accepted in CLJ files too? Or I shoud use reader conditionals in CLJC files? At least Clojure compiler does not complain about this option.#2022-10-0716:13imrelinter idea: functions that should probably not be used as the reducing function in a call to transduce based on https://twitter.com/cgrand/status/1578401747835445252#2022-10-0716:15borkdudewe already have that for reduce @imre: reduce-without-init#2022-10-0716:15imrethat's different#2022-10-0716:16borkdudehow?#2022-10-0716:16imre
(transduce identity - 0 (range 5))
=> 10
it's about using - as the reducing fn
#2022-10-0716:17imrevs
(transduce identity (completing -) 0 (range 5))
=> -10
#2022-10-0716:17imre(which is what I would expect if I looked at the first snippet)#2022-10-0716:17borkdudeyes, it is similar to reduce-without-init, but then as the reducing function#2022-10-0716:17borkdudeoh I see, it is different ;)#2022-10-0716:18imreit's about the completing arity, not the ~starting~ init one 🙂#2022-10-0716:19borkdudeFeel free to provide an issue with example cases#2022-10-0716:19imrewill do 🙂#2022-10-0716:29imrehttps://github.com/clj-kondo/clj-kondo/issues/1835#2022-10-0717:18Noah Bogartoof, that's complicated#2022-10-0917:16seancorfieldFollowing on from a discussion in #C03S1KBA2 I would like to see clj-kondo flag this as problematic code:
(defn panda
  [& {:keys [a b c d e f g h]
      :or {a 1
           b a
           c b
           d c
           e d
           f e
           g f
           h g}}]
  [a b c d e f g h])

(defn sad-panda
  [& {:keys [a b c d e f g h i]
      :or {a 1
           b a
           c b
           d c
           e d
           f e
           g f
           h g
           i h}}]
  [a b c d e f g h i])
The first fn works by accident as the defaults map is small and uses an array map so the keys stay in order and defaults can depend on earlier ones. The second fn fails because the defaults map is larger and uses a hash map and so the keys are in a different order. This has come up before and I'm pretty sure Alex confirmed that this was never intended to work -- it's just an accident of implementation in the small case. Could clj-kondo detect that the default values are depending on each other?
#2022-10-0917:51borkdudeIs that this issue? Feel free to upvote: https://github.com/clj-kondo/clj-kondo/issues/916#2022-10-0917:52borkdudeI think it's a similar but not exactly the same issue#2022-10-0917:52borkdudeMaybe add a comment to the issue#2022-10-0918:17seancorfieldAdded a 👍:skin-tone-2: Interesting group of related issues there around destructuring. Sorry I didn't just search the open issues before commenting 😕#2022-10-0918:17borkdudeNo problem, there are so many :)#2022-10-0918:19seancorfieldThe burden of popularity 🙂#2022-10-0920:13Noah BogartOooooh this is a brain tickler. I might give this a go, intrigued by how I’d go about it.#2022-10-0920:34borkdudeIt's fairly easy to implement#2022-10-0920:42borkdudeProbably the hardest part is a good name. Suggestions welcome :)#2022-10-0921:20Noah Bogart:or-local-binding, :or-non-local-binding, :or-bindings, :or-expression-bindings, etc#2022-10-0921:25borkdude:destructured-binding-in-default?#2022-10-1014:49Noah Bogart:self-referential-default-bindings lol#2022-10-1014:51borkdudeI think the issue is now beyond self-referential bindings, any destructured binding (from the same map) in defaults is considered undefined now#2022-10-1014:52Noah Bogartor maybe :self-referential-destructured-bindings because any sort of self-reference is undefined#2022-10-1014:53borkdudeKeep trying :)#2022-10-1014:54Noah Bogarti'm using self-referential to mean "from the same map". i don't have a good phrase at hand that means the same#2022-10-1014:54borkdudeundefined-default#2022-10-1014:55Noah Bogart(just in case, i love these bikeshedding discussions but if you find something you like, you don't need to idk get my permission or blessing lol)#2022-10-1014:56Noah Bogartundefined-default is pithy and short but doesn't tell me what exactly it's protecting against unless I already know the error#2022-10-1014:56borkdudeI'll wait for @U04V70XH6 to throw in a good name suggestion as well#2022-10-1015:43seancorfieldAfter several of the suggestions here, I have nothing 😆#2022-10-1000:34JRIs there a way to use the repl to launch the clj-kondo? When I use Calva to Jack-in, and then evaluate main.clj, I get
clj꞉clj-kondo.main꞉> 
; Evaluating file: main.clj
; Syntax error (ClassNotFoundException) compiling at (src/clj_kondo/main.clj:1:1).
; clj-kondo.main
; Evaluation of file main.clj failed: class clojure.lang.Compiler$CompilerException
I've been looking into https://github.com/clj-kondo/clj-kondo/issues/1824 and it would be great to either use the REPL when making code changes, or to debug the code with something like flow-storm. I can do builds as they are described on https://github.com/clj-kondo/clj-kondo/blob/master/doc/build.md, but doing a full build is slow.
#2022-10-1009:36borkdudeHi!#2022-10-1009:37borkdudeYes, of course, you can use clj-kondo from the REPL:
$ clj
Clojure 1.11.0
user=> (require '[clj-kondo.main])
nil
user=> (require '[clj-kondo.core :as clj-kondo])
nil
user=> (:findings (with-in-str "(+ :foo)" (clj-kondo/run! {:lint ["-"]})))
[{:filename "<stdin>", :row 1, :col 4, :end-row 1, :end-col 8, :type :type-mismatch, :message "Expected: number, received: keyword.", :level :warning}]
#2022-10-1009:38borkdudeThanks for looking into the issue. Let me know if you need more info.#2022-10-1009:38borkdudeOh, let me also try the jack-in in Calva#2022-10-1009:40borkdudeWorks fine over here. I chose jack-in, deps.edn, alias clj-kondo/dev#2022-10-1013:10JRThanks! This is among my first dive into a real-world clojure project, so I appreciate the guidance#2022-10-1015:54nonrecursivehey y’all, I’ve added this to my config.edn yet I’m still getting a warning:
{:linters
 {:unresolved-symbol
  {:exclude [(clojure.test/is [match?])]}}}
Any idea what might be going on here? One place I’m getting a warning is https://github.com/donut-power/datapotato/blob/main/datapotato/test/donut/datapotato/atom_test.cljc#L74
#2022-10-1016:03imre[matcher-combinators.test :refer [match?]] is how I solve this#2022-10-1016:18borkdudeyou might also have to add cljs.test in the config#2022-10-1016:45nonrecursiveadding cljs.test fixed it! thank you#2022-10-1016:55tedcushmanI have been trying to figure out how to resolve an unexpected inline def warning related clojure.spec. The :inline-def occurs when using inline keys specs inside a def or defn, for example:
(require '[clojure.spec.alpha :as s])
;; Simplified case
(def foo (s/keys :req-un [::abc] :opt-un [::xyz]))
;; Basic use case
(defn gen-my-map [] (s/gen (s/keys :req-un [::abc] :opt-un [::xyz])))
I get warnings for these using version 2022.10.05 and other recent versions. I know the specs are macro driven, but I don't see any signs that keys generates any defs.
#2022-10-1017:00borkdudeI can't reproduce this locally. Can you make a standalone file including extension and upload it here? Back in an hour.#2022-10-1017:16tedcushmanUgh, I created a test file and get the warning in one project, but not in another, even with the config.edn moved out of the way. Looks like I need to work a little more on reproducing this.#2022-10-1017:27tedcushmanHere is the example as a file. Sometimes I get warnings, sometimes I don't, still trying to figure out what triggers the different results. (cache, configuration, copied configurations, etc.)#2022-10-1017:33tedcushmanUsually I get the following output when checking the file above, but sometimes I don't. Haven't found a clear pattern yet.
$ clj-kondo --version
clj-kondo v2022.10.05

$ clj-kondo --lint inline_spec.clj
inline_spec.clj:4:10: warning: inline def
inline_spec.clj:7:28: warning: inline def
linting took 12ms, errors: 0, warnings: 2
#2022-10-1017:40tedcushmanNevermind, I found the following nonsense in my global config.edn file.
{:lint-as {clojure.spec.alpha/keys clojure.core/def}}
Don't know how that got there. Thanks for looking into this.
#2022-10-1017:49borkdudeAh, glad it's solved now :)#2022-10-1019:45sheluchinFulcro has a large collection of generated DOM element factory https://github.com/fulcrologic/fulcro/blob/d9f6090219900798fb2f6640cf44d6c319a4f99f/src/main/com/fulcrologic/fulcro/dom.cljs#L17 with server and client support. clj-kondo doesn't provide arglists or docstrings for these factories in the :var-definition analysis. Is there a recommended way of dealing with things like this?#2022-10-1019:45sheluchinHere is the definition for it:
[{:end-row 30
     :meta nil
     :name-end-col 11
     :name-end-row 17
     :name-row 17
     :ns com.fulcrologic.fulcro.dom
     :name a
     :defined-by cljs.core/declare
     :filename "fulcrologic/fulcro/src/main/com/fulcrologic/fulcro/dom.cljs"
     :col 1
     :name-col 10
     :end-col 45
     :row 17}
#2022-10-1019:46sheluchinWhereas the generated docstring for all of them is like this:
*com.fulcrologic.fulcro.dom/div*
  [& args]
  Returns a React DOM element. Can be invoked in several ways

These two are made equivalent at compile time
(div "hello")
(div nil "hello")

These two are made equivalent at compile time
(div {:onClick f} "hello")
(div #js {:onClick f} "hello")

There is also a shorthand for CSS id and class names
(div :#the-id.klass.other-klass "hello")
(div :#the-id.klass.other-klass {:onClick f} "hello"))
#2022-10-1019:53sheluchinThe :var-usages info also does not include :arity:
{:end-row 6
     :name-end-col 51
     :name-end-row 6
     :name-row 6
     :name div
     :filename "ui/reports/function_profile.cljs"
     :from ui.reports.function-profile
     :col 48
     :name-col 48
     :end-col 51
     :refer true
     :row 6
     :to com.fulcrologic.fulcro.dom}
That is produced from this code:
(div :.sixteen.wide.column.segment "test")
#2022-10-1020:04borkdudeTo make this more tooling friendly, one could choose to generate the code to disk instead of only via a macro at compile time#2022-10-1020:04borkdudeOr write a hook which expands this call into stuff that clj-kondo understands better#2022-10-1020:06sheluchinIs there a way to write a single hook that would cover all of those generated items? They essentially expand to the same kind of form and all have the same (almost) docstring.#2022-10-1020:06borkdudea single hook yes, but you would need to have a mapping for all of those vars in the config currently#2022-10-1020:07borkdudeso {foo/a hook foo/b hook foo/c hook} etc#2022-10-1020:10sheluchinThat would only help with the :var-usage data and not the :var-definition, right?#2022-10-1020:10sheluchinHaven't written any hooks myself yet..#2022-10-1020:31borkdudethat would help with var-definition since you can expand this into a hook which generates the right var definition#2022-10-1020:35sheluchinAlright, thank you. I will do it for these Fulcro items. Are you otherwise interested in receiving reports about such analysis peculiarities? I'm running clj-kondo analysis on many libraries and trying to fit the results into a normalized SQL schema. In most cases things work just as they should but there are quite a number of mismatches across the ecosystem. By mismatches I mean cases where a var usage doesn't match up to some expected var definition foreign key.#2022-10-1020:37borkdudeYeah, sure, anything that can improve the quality of the analysis is surely welcome#2022-10-1020:37borkdudeAnd I appreciate your work on this so far#2022-10-1021:17sheluchinHappy to help! I'm thinking if I create a mismatch report it could help identify the libraries that need the most help or have the biggest ecosystem impact.#2022-10-1108:26seriogaIt looks like we need linter for docstrings markdown :thinking_face: https://github.com/strojure/parsesso/search?q=Fix+Markdown+code+fences&amp;type=commits#2022-10-1109:09borkdude@U0HJNJWJH If you use #C03EC4DD26S you can make a branch, check in your API.md and then you can see immediately how it looks on github#2022-10-1109:35seriogawill I see same as at cljdoc?#2022-10-1109:44borkdudeoh, I don't know about that#2022-10-1109:48seriogaOK, additional testing required :-)#2022-10-1114:25lread@U0HJNJWJH you can https://github.com/cljdoc/cljdoc/blob/master/doc/running-cljdoc-locally-author.adoc, you can also https://github.com/cljdoc/cljdoc/blob/master/doc/userguide/for-library-authors.adoc#overriding-articles-revision after a clojars release. Drop by #C8V0BQ0M6 if you need/want help/info.#2022-10-1402:46pavlosmelissinosThis
(let [size 1
        seed 500]
    (gen/generate ::c/some-spec size seed))
gives me an error on emacs with flycheck: clojure.test.check.generators/generate is called with 3 args but expects 1 or 2 The 3-args call is correct (the code evaluates and the docs https://clojure.github.io/test.check/clojure.test.check.generators.html#var-generate) so could someone tell me what's going on here? 🙂
#2022-10-1414:13borkdudeCan you try linting the dependency that you have on your classpath with clj-kondo? Could be a built-in vs what you have difference#2022-10-1414:15pavlosmelissinosDamn, I should have thought of that 😞. Yes I'll try that and let you know if it's a clj-kondo issue#2022-10-1414:18borkdudeNo worries#2022-10-1418:36pavlosmelissinosDoesn't seem to be an emacs issue.
pavlos$ clojure -M:clj-kondo --fail-level error --lint src/lala.clj | grep error
...
src/lala.clj:5:1: error: clojure.test.check.generators/generate is called with 3 args but expects 1 or 2
linting took 81ms, errors: 1, warnings: 0
src/lala.clj contains:
(ns lala
  (:require [clojure.spec.alpha :as s]
            [clojure.test.check.generators :as gen]))

(gen/generate (s/gen int?) 1 500)
pavlos$ clojure -M:clj-kondo --version                                             
clj-kondo v2022.10.05
Should I open an issue on Github?
#2022-10-1418:37pavlosmelissinosThe clj-kondo alias in deps.edn looks like this:
:clj-kondo {:replace-deps {clj-kondo/clj-kondo {:mvn/version "RELEASE"}}
                         :main-opts ["-m" "clj-kondo.main" ]}
#2022-10-1418:38borkdudeDid you lint your dependencies?#2022-10-1418:44borkdude@UEQPKG7HQ
clojure -M:clj-kondo --lint $(clojure -Spath) --dependencies
#2022-10-1418:44borkdudeafter that, try again#2022-10-1419:06pavlosmelissinosYou're right, it works now... The instructions are very prominent in the clj-kondo docs as well, not sure how I missed it. However, I don't really understand why clj-kondo recognized the 1- and 2-arity signatures but needed a cache refresh for the 3-arity. I would understand it if the 3-arity was a recent addition but it was actually https://github.com/clojure/test.check/blame/b6a318af92e836f1f20960f38a5944168b88d60d/src/main/clojure/clojure/test/check/generators.cljc#L198.#2022-10-1419:07borkdudeMaybe you first linted with an old dependency from 6 years ago? I can't reproduce the issue locally :)
$ clj-kondo --lint - <<< '(ns lala
  (:require [clojure.spec.alpha :as s]
            [clojure.test.check.generators :as gen]))

(gen/generate (s/gen int?) 1 500)'
linting took 28ms, errors: 0, warnings: 0
#2022-10-1419:11pavlosmelissinosAh, yes. That's very likely, the project in question had some dependencies that were quite old and we upgraded them recently. Would it be possible for clj-kondo to check if the cache is outdated when it runs and warn the user if so?#2022-10-1419:12borkdudehow are you using clj-kondo, from your editor or command line?#2022-10-1419:16pavlosmelissinosUsually from emacs (during development) but every now and then I'll do a full sweep of the entire project as a maintenance task#2022-10-1419:16borkdudeand which editor?#2022-10-1419:16borkdudeand using which "plugin"?#2022-10-1419:16pavlosmelissinosemacs + flycheck (is that what you mean?)#2022-10-1419:17borkdudeand you're not using lsp right?#2022-10-1419:17pavlosmelissinosnot for Clojure#2022-10-1419:19borkdudeok. clj-kondo doesn't do anything to keep in sync with your dependencies automatically, but you can run:
clj-kondo --lint $(clojure -Spath) --dependencies --parallel
which is pretty fast since it will skip already linted jar files
#2022-10-1419:20borkdudeso any time you change your project / deps file, you can re-run this. clojure-lsp does this automatically for you#2022-10-1419:47pavlosmelissinosI see, that's good to know! I'll see if I can set up emacs to mimic that fire-and-forget behaviour, thanks for all the info 🙂#2022-10-1420:08borkdudeany time#2022-10-1413:55sheluchinPerhaps there should be a linter that warns when not using https://github.com/bbatsov/clojure-style-guide#use-idiomatic-namespace-aliases?#2022-10-1414:12borkdudeWe already have that as the :consistent-alias linter#2022-10-1414:15sheluchinI did see that one, but it requires user configuration. My thought was that including a default list with the aliases listed in the Clojure Style Guide would be helpful to make code bases more consistent. Not sure if putting a default list on :consistent-aliases or adding a whole new linter for it would be better.#2022-10-1414:17borkdudeWe could add an option to :consistent-aliases that populates the idiomatic list from the community guide#2022-10-1414:17borkdude:community-guide true#2022-10-1414:18borkdudeHaving to use the spec alias for clojure.spec.alpha already puts me off though :P
#2022-10-1414:21sheluchinThat is a nice idea. I wonder if such a flag can be useful in other linters as well. > Having to use the spec alias for clojure.spec.alpha already puts me off though 😛 That straight up seems like a bug in the community guide :face_with_raised_eyebrow: How is that idiomatic when every bit of official documentation uses s? I guess this is a good argument to making the entries in the :community-guide option override-able with explicit configuration.#2022-10-1414:22borkdudehaha#2022-10-1414:23borkdudeI had to laugh a bit because of the story "someone suggests linter for community guide aliases" and then the conversation goes "how is that entry in the guide idiomatic!"#2022-10-1414:24sheluchinThis turns clj-kondo configs into a voting mechanism.#2022-10-1414:26borkdudeI guess you could also do the community guide aliases as a clj-kondo library which is merged automatically when imported#2022-10-1414:26sheluchinI'll file an issue for the :community-guide/idiomatic aliases flag so it's on the radar. Seems like it could use some more thought.#2022-10-1414:27sheluchin> I guess you could also do the community guide aliases as a clj-kondo library which is merged automatically when imported I'm not sure what you mean by that..?#2022-10-1414:27borkdudeSame mechanism as hooks#2022-10-1414:32sheluchinDo you mean to create a new lib that would just export the community guide alias configuration for clj-kondo so that anyone that wants to use the list can do so by installing the lib?#2022-10-1414:32borkdudeyes#2022-10-1414:32borkdudeby adding the lib to your :deps#2022-10-1414:36sheluchinInteresting approach. I guess that would require no new work for clj-kondo but would require maintaining a separate library and users would need to understand the path and install the dep.#2022-10-1414:36borkdudeyes#2022-10-1414:36sheluchinOkay, @U04V15CAJ. Thanks for your consideration. I will log the ideas in the ticket.#2022-10-1414:36borkdudebut it would also not need a new release of clj-kondo to get these defaults#2022-10-1414:37sheluchinIn the least it'll require some clj-kondo documentation to explain it, I think.#2022-10-1414:39borkdudeSure#2022-10-1415:13skylize> That straight up seems like a bug in the community guide :face_with_raised_eyebrow: How is that idiomatic when every bit of official documentation uses s? Seems like an issue should also be opened with the style guide to get this fixed.#2022-10-1417:05Noah BogartI think having a “community-guide true” flag would be nice. Extra dependencies are hard, especially when running clj-kondo as a standalone bin instead of a project dependency.#2022-10-1512:05sheluchinhttps://github.com/bbatsov/clojure-style-guide/issues/245#2022-10-1614:53sheluchinhttps://github.com/clj-kondo/clj-kondo/issues/1839#2022-10-1416:21Sam Ritchiethis is a bit strange; I just pushed to a sicmutils branch for the first time in a while, and the linter is failing on many of my cljc files with
Warning: Unknown require option: :include-macros
Here is the output: https://github.com/sicmutils/sicmutils/actions/runs/3251402996/jobs/5336339401
#2022-10-1416:21Sam RitchieLooks like this is with
Downloading  to /tmp
#2022-10-1416:22Sam RitchieLocally, I get no errors with
[
#2022-10-1416:22lreadHeya @U017QJZ9M7W this is a little bug that slipped into last release.#2022-10-1416:23Sam Ritchiegot it, no worries, glad to hear it’s something that’s on your radar!#2022-10-1416:23borkdudeIt's already been fixed on master#2022-10-1416:23borkdudeI guess I could do a new release for just that :-s#2022-10-1416:24lreadhttps://github.com/clj-commons/rewrite-clj/blob/c0e9184a9b5566e7932cff4f3769a2c49e647f31/.clj-kondo/config.edn#L18. Easy peasy.#2022-10-1416:25borkdudeSince this is the only reported unknown require option in a week, I think I'll do a new release this weekend and leave the linter on#2022-10-1416:26borkdudeWith an :exclude option which still has to be made#2022-10-1416:26Sam Ritchiesounds good#2022-10-1419:34borkdude@U017QJZ9M7W I just published a new version of clj-kondo to clojars, could you test with that?#2022-10-1419:38Sam Ritchiesure, will do shortly#2022-10-1419:43borkdudeClj-kondo: static analyzer and linter for clojure Small intermittent release 2022.10.14 • https://github.com/clj-kondo/clj-kondo/issues/1831: Add :redundant-fn-wrapper support for keyword and binding calls (https://github.com/NoahTheDuke) • https://github.com/clj-kondo/clj-kondo/issues/1830: Fix warning on :include-macros in .cljs and .cljc for :unknown-require-option linter. (https://github.com/NoahTheDuke) • https://github.com/clj-kondo/clj-kondo/issues/1238: Build a linux/aarch64 executable in CI (https://github.com/cap10morgan) • Add :exclude option to :unknown-require-option • Enable :unused-value by default • Publish .sha256 files along with released artifacts#2022-10-1515:36borkdudeNow enabled by default in the latest clj-kondo:#2022-10-1520:11Fredrik AnderssonDoes anyone know why clj-kondo doesn't recognize binding made in reagent macro with-let?#2022-10-1520:17Fredrik AnderssonI think i found it. Thanks#2022-10-1614:39Fredrik Anderssonhowever, now I have created my own macro - how do I make clj-kondo lint that correctly? I have two linter errors coming from my macro#2022-10-1614:49lassemaattahttps://clojurians.slack.com/archives/CPABC1H61/p1658985733025239?thread_ts=1658978704.619419&amp;cid=CPABC1H61 (original question was regarding clojure-lsp but the situation is the same)#2022-10-1614:50Fredrik Anderssonthanks, ill look into it#2022-10-1614:55sheluchinYou may find https://github.com/clj-kondo/hooks-workshop-clojured-2022 helpful.#2022-10-1615:09borkdude@U01JYUZRS4V what kind of macro? Do you have an example of its usage?#2022-10-1615:37borkdudeI'm asking since the syntax of your macro may make it easier or less easy to configure it for clj-kondo#2022-10-1617:45Fredrik Andersson;; define component that depends on resolvers (sub/defcomp app [user-id] [boot [:firebase firebase-config] individual [:firestore [:individual user-id]]] (case (:state @boot) :starting [:div "booting"] :unauthenticated [:div "unauthenticated"] :authenticated (layout/app {:logo [:div.bg-green-100 "Logo"] :user [:div.bg-blue-100 "User"] :navigation [:div.bg-yellow-100 [:div "lalalala"]] :content-top [:div.bg-red-100 "Content top"] :menu [:div.bg-purple-100 "Hamburger"] :content [:div.bg-pink-100 [:div "lalalala"]]}) [:div "Error"]))#2022-10-1617:45Fredrik Anderssonthis is the test case for the macro#2022-10-1617:48Fredrik Anderssonit becomes a (defn app ...) that in turn use reagent with-let to setup subscriptions to firestore#2022-10-1617:55Fredrik Anderssonas far as I understand, I should write a hook that rewrites the code into a (defn <name> [] (let [..#2022-10-1617:58Fredrik Anderssonahh, now I see that everything would be easier if I just let the macro be a new (let bindings instead of the whole function#2022-10-1618:26Fredrik Anderssonthanks everybody for your help - I finally solved it by rewriting my macro into a pure binding macro#2022-10-1618:43borkdudemakes sense#2022-10-1618:44Fredrik Anderssonyes, I realize now that I was trying to do too much in my macro and that it wouldn't be according to general consensus#2022-10-1618:44Fredrik Anderssonor convention#2022-10-1618:45borkdudeWith clj-kondo in general it works best if your new macros align with some existing macro so you can use :lint-as but if not, there's always other ways to do stuff: either by suppressing warnings, or writing hooks.#2022-10-1614:40Fredrik Anderssonfirst, it doesn't recognize that my macro generates a defn and second it doesnt recognize let bindings#2022-10-1705:26onetomis there a place, which collects recommended :lint-as definitions for popular clojure libraries?#2022-10-1707:26borkdudeThe best place is in that library itself#2022-10-1707:27borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2022-10-1708:19onetomi saw that page, but on 1st skimming i missed the link to https://github.com/clj-kondo/config btw, this is the config i needed:
❯ cat ~/.config/clj-kondo/config.edn 
{:lint-as {; 
           clojure.test.check.properties/for-all clojure.core/let
           clojure.test.check.clojure-test/defspec clojure.core/def #_clj-kondo.lint-as/def-catch-all}}
so i guess this config should go into clj-kondo/config for reusability.
#2022-10-1708:43borkdudeYes. I won't get my hopes up to get this config into a core library so maybe it's best to create another library with just that config which you can then add to your deps. I've been considering this for a while#2022-10-2115:52vlad_pohEverytime i use org.httpkit client in calva i get “Unresolved var” for each function. Any idea on what i’m doing wrong?
org.httpkit.client/get
[url & [opts callback]]
[url & [callback]]
Issues an async HTTP GET request. See request for details.

Unresolved var: c/getclj-kondo(unresolved-var)
#2022-10-2115:57borkdude@U06GMV0B0 The issue is that these vars have been created via a custom macro. https://github.com/http-kit/http-kit/blob/cf1365167c5a2447f66ea2c0f4541a81114d2f74/src/org/httpkit/client.clj#L308 you can solve this by adding {:lint-as {org.httpkit.client/defreq clojure.core/def}} to your config and the restart your workspace#2022-10-1712:44sheluchinWould a :consistently-aliased flag for the :consistent-alias linter be helpful? Setting it to true would show warnings on usages of a fully qualified namespace symbol (and keyword, ideally) when that same ns has a :consistent-alias configuration.#2022-10-1713:14bitbltHello#2022-10-1713:23bitbltI'm trying to fix an Unresolved var warning in clojure-lsp that comes from clj-kondo. I'm generating a project from the re-frame-template using this:
clojure -Tclj-new create :template re-frame :name sample/playground :output sample-playground :args '[+kondo +garden +routes "+10x"]'
The generated file styles.cljs has lots of clj-kondo errors/warnings by default, most of them that I managed to fix in this PR: https://github.com/day8/re-frame-template/pull/174 I'm trying to solve the last one, an Unresolved var: deg which is referred from garden.units namespace. I tried adding garden.units/defunit clojure.core/def to :lint-as of .clj-kondo/config.edn, seeing deg is defined as (defunit deg), without much success. Any ideas?
#2022-10-1713:33borkdudeYou need to re-lint your dependencies with this configuration in place#2022-10-1713:34bitbltFirst of all, honored 🙂#2022-10-1713:35bitbltI'm kind of now transitioning into the clojure ecosystem, could you explain what do you mean by re-linting?#2022-10-1713:35borkdudeIt might also be a good idea to submit those configurations to the libraries themselves rather than just the templates. https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration See here for examples: https://github.com/clj-kondo/clj-kondo/discussions/1528#2022-10-1713:35borkdudeRe-linting just means: analyze the code again with clj-kondo#2022-10-1713:36borkdudeSo on the command line for example:
clj-kondo --lint $(clojure -Spath) --dependencies
#2022-10-1713:36borkdudeand then the garden namespace is seen again by clj-kondo, but this time with your new lint-as configuration#2022-10-1713:36borkdudeand then clj-kondo sees there is a var deg being defined#2022-10-1713:38borkdudeWhat also might help is blow the clj-kondo and lsp cache:
rm -rf .lsp/.cache
rm -rf .clj-kondo/.cache
#2022-10-1713:38borkdudeand then restart your editor#2022-10-1713:39borkdudeNormally clojure-lsp should notice that the clj-kondo config has changed though#2022-10-1713:39borkdudeand re-lint the code automatically#2022-10-1713:41bitbltI tried rm -rf .lsp .clj-kondo/* (except config.edn), running the clj-kondo command above, and again opening my editor#2022-10-1713:41bitbltStill the same#2022-10-1713:42borkdudecan you check out the repo in another directory and open it there?#2022-10-1713:42borkdudeand is it possible to make a repro that I can download locally?#2022-10-1713:45bitbltI believe it is!#2022-10-1713:45bitbltLet me make you an oneliner#2022-10-1713:47borkdudeBack in 30 minutes#2022-10-1713:54bitbltGenerate a sample re-frame project using:
clojure -Tclj-new create :template re-frame :name sample.playground :output sample-playground :args '[+kondo +garden +routes "+10x"]'
and then just replace the .clj-kondo/config.edn with the patched one from my PR:
{:lint-as {day8.re-frame.tracing/defn-traced clojure.core/defn
           day8.re-frame.tracing/fn-traced clojure.core/fn
           garden.def/defcssfn clojure.core/defn
           garden.def/defkeyframes clojure.core/def
           garden.def/defrule clojure.core/def
           garden.def/defstyles clojure.core/def
           garden.def/defstylesheet clojure.core/def
           spade.core/defglobal clojure.core/def
           spade.core/defclass clojure.core/def}
 :linters {:unresolved-symbol {:exclude [goog.DEBUG]}
           :unused-namespace {:exclude [cljs.repl]}
           :unused-referred-var {:exclude {cljs.repl [Error->map
                                                      apropos
                                                      dir
                                                      doc
                                                      error->str
                                                      ex-str
                                                      ex-triage
                                                      find-doc
                                                      print-doc
                                                      pst
                                                      source]}}}}
Then just cd into sample-playground, open your editor to styles.cljs and see!
#2022-10-1713:54bitblt(Description for PoC practically lives in the above PR too)#2022-10-1714:33borkdudeIs it possible to prepare a repro which I can directly clone?#2022-10-1714:33borkdudeI don't have the clj-new alias readily available etc#2022-10-1714:33bitbltOfc, give me a minute#2022-10-1714:36bitbltHere you go#2022-10-1714:36bitblthttps://github.com/agorgl/clj-kondo-poc#2022-10-1714:38borkdudeThanks, I can repro now, checking into it#2022-10-1714:45borkdudeSo if I go into the garden unit project itself and configure it, it does work correctly#2022-10-1714:47bitbltWeird?#2022-10-1714:49borkdudeSo when I add these deps:
$ cat deps.edn
{:deps {garden/garden {:mvn/version "1.3.10"}
        garden/garden-units {:mvn/version "1.0.0-RC2"}}}
#2022-10-1714:49borkdudeand then run:
clj-kondo --lint $(clojure -Spath) --dependencies
#2022-10-1714:49borkdudeand then run:
clj-kondo --lint src/clj_kondo/poc/styles.cljs
#2022-10-1714:49borkdudeI see no warnings anymore#2022-10-1714:50borkdudeSo this must be a problem with #CPABC1H61 and perhaps the shadow-cljs.edn deps / cc @UKFSJSM38#2022-10-1714:53borkdudeI don't see the garden-units library appear when doing this:
npx shadow-cljs classpath
#2022-10-1714:53borkdudecould that be part of the issue?#2022-10-1714:54ericdalloprobably, clojure-lsp just do programatically those clj-kondo calls you pasted#2022-10-1714:54ericdalloactually, clojure-lsp merges the classpath of both deps.edn + npx#2022-10-1714:54ericdallothe lsp-clojure-server-info should show the classpath#2022-10-1714:55borkdude
rm -rf .clj-kondo/.cache
clj-kondo --lint $(npx shadow-cljs classpath) --dependencies
clj-kondo --lint src/clj_kondo/poc/styles.cljs
src/clj_kondo/poc/styles.cljs:6:6: warning: Unsorted namespace: garden.units
#2022-10-1714:55borkdude(that unsorted warning comes from my home config)#2022-10-1714:55borkdudeSo this sequence of commands seems to work#2022-10-1714:56ericdalloand that warning is expected, right?#2022-10-1714:56borkdudeyes#2022-10-1714:56ericdallolet me try the repro#2022-10-1714:56borkdudeand now I also get no warning when deleting the caches again and restarting the project#2022-10-1714:57borkdude@U03PYN9FG77 Could it be that you just need to run npm install in this project first?#2022-10-1714:57ericdallo@U04V15CAJ what is the repro exactly on that repo?#2022-10-1714:58borkdude@UKFSJSM38
src/clj_kondo/poc/styles.cljs:6:27: warning: Unresolved var: deg
#2022-10-1714:59borkdudebut I can't repro that anymore#2022-10-1714:59borkdudeoh wait, maybe remove my deps.edn again#2022-10-1715:00ericdalloI can repro the warning. The project doesn't have any deps.edn right? so the only classpath option is from npx#2022-10-1715:01bitbltYes#2022-10-1715:01ericdalloand npx shadow-cljs classpath returns "~/.m2/repository/garden/garden/1.3.10/garden-1.3.10.jar , is the hook inside that version?#2022-10-1715:01borkdudeI can only repro it from a clean state#2022-10-1715:02bitbltI tried fresh clone -> npm i -> clj-kondo --lint $(npx shadow-cljs classpath) --dependencies , opening my editor in styles.cljs and I can still repro it#2022-10-1715:03ericdalloI did the same without calling clj-kondo, just opening with clojure-lsp, which should end in the same#2022-10-1715:03borkdudeThe fact that npx shadow-cljs classpath isn't showing this units library is weird right?#2022-10-1715:03ericdallooh if the hook is inside that units library, that's the problem indeed.#2022-10-1715:04borkdudegarden itself doesn't seem to depend on that https://github.com/noprompt/garden/blob/master/project.clj#2022-10-1715:04ericdalloI only see garden on shadow-cljs.edn, shouldn't you include garden/garden-units as well?#2022-10-1715:05bitbltIts a namespace within garden? https://github.com/noprompt/garden/blob/master/src/garden/units.cljc#2022-10-1715:05bitbltI don't think it is a separate library / dependency#2022-10-1715:05borkdudeoh...#2022-10-1715:06borkdudeThis is confusing since there is also a library with that namespace#2022-10-1715:06borkdudebut ok, that mystery is solved#2022-10-1715:07ericdalloso, no bugs anywhere right? :) just confusing deps/ns#2022-10-1715:09bitbltWell there is still a confusing warning#2022-10-1715:10ericdalloAFAICS that happens because npx classpath doesn't include garden/garden-units which has the hook, only garden/garden#2022-10-1715:11borkdudeI also needed to add garden.units/defunit clojure.core/def to the config#2022-10-1715:11bitbltWhat hook?#2022-10-1715:11borkdudehere https://github.com/agorgl/clj-kondo-poc/blob/master/.clj-kondo/config.edn#2022-10-1715:11borkdude:lint-as#2022-10-1715:12ericdalloyeah, my bad, @U04V15CAJ is correct, adding that config is enough to solve since the problem is the defunit not being recognized as a macro that defines a var#2022-10-1715:13bitbltAh damn, I literally tried this before as I described at first message#2022-10-1715:13bitbltIn a clean clone works#2022-10-1715:13bitbltCache was not my friend#2022-10-1715:13bitblt@U04V15CAJ any good tip to make defglobal Unused public var disappear too?#2022-10-1715:14borkdudeunused public var is @UKFSJSM38’s department ;)#2022-10-1715:15ericdallo@U03PYN9FG77 check https://clojure-lsp.io/settings/#clojure-lspunused-public-var#2022-10-1715:16bitbltI just have to say#2022-10-1715:16bitbltYou are probably the best community I've ever encountered in my whole career#2022-10-1715:16bitbltThanks guys, you inspire me to become a Clojurist#2022-10-1715:19bitbltUpdated re-frame template fix PR, I hope the maintainer accepts it soon#2022-10-1715:19bitblthttps://github.com/day8/re-frame-template/pull/174/files#2022-10-1715:19bitbltHave a nice day!#2022-10-1715:29borkdudeYou too :)#2022-10-1921:03Noah BogartI opened an issue about adding a linter from eastwood to clj-kondo. Would you (borkdude) be interested in adding other linters from eastwood and kibit?#2022-10-1921:04borkdudelet's discuss on a case by case basis.#2022-10-1921:04Noah BogartCool, thanks#2022-10-1923:06noogaI'm using vscode to edit let-go files, which are mostly valid Clojure. I get Can't parse myfile.lg, No matching clause: :unknown [Ln 1, Col 1] from clj-kondo(syntax) in almost every file, regardless of the content, always on the first line. It only happens when the files have .lg extension - I've associated it with Clojure though. Is there a way to make clj-kondo respect .lg 🙂?#2022-10-2006:35borkdudeRepro?#2022-10-2211:43nooga1. make sure your VSCode global settings.json has the following set:
"files.associations": {
    "*.lg": "clojure"
  },
2. create an empty folder and open it in fresh VSCode window, 3. create and open file foo.lg 4. In foo.lg paste
(ns foo)

(println 1)
result:
#2022-10-2211:44noogathe error goes away when you rename foo.lg to foo.clj#2022-10-2211:44borkdudeI'll test in emacs as well#2022-10-2211:49borkdudeIn emacs it works fine when I enter clojure-mode this is because flycheck-clj-kondo derives the language fallback from the mode you're in https://github.com/borkdude/flycheck-clj-kondo/blob/ff7bed2315755cfe02ef471edf522e27b78cd5ca/flycheck-clj-kondo.el#L88-L91 but I'll make clj-kondo more lenient that when the language is unknown it falls back to clojure#2022-10-2211:49borkdudeO wait, this is already the case:
$ clj-kondo --lint /tmp/foo.lg
/tmp/foo.lg:5:1: error: Unresolved symbol: x
#2022-10-2211:50borkdudeI suspect that clojure-lsp is passing lang as lg or so:
$ clj-kondo --lint /tmp/foo.lg --lang lg
/tmp/foo.lg:0:0: error: Can't parse /tmp/foo.lg, No matching clause: :lg
#2022-10-2211:50borkdudeIt should just not pass --lang if it's something unknown. cc @UKFSJSM38#2022-10-2216:39ericdalloI thought we fixed that, I'll take a look#2022-10-2216:40nooga👀#2022-10-2321:17ericdalloFixed on master, it will only pass lang if not unknown, available on nightly build#2022-10-1923:45skynetit looks to me like I'm getting from the new :unused-value linter on a macro from a library I'm using. specifically this one: https://github.com/ptaoussanis/nippy/blob/a2e03bef5e3aaabb1351367085334cf8feadcd06/src/taoensso/nippy.clj#L1939-L1968 maybe :unused-value should be disabled for things inside macros?#2022-10-2006:35borkdudePlease provide a repro as in a file which I can readily lint locally #2022-10-2017:49skynetsorry, I'm not able to reproduce it outside of the project it's in: https://github.com/skynet-gh/skylobby/blob/master/graal/clj/skylobby/core.clj#L37-L39
$ clj-kondo --lint graal/clj/skylobby/core.clj | grep Unused
graal/clj/skylobby/core.clj:37:3: info: Unused value
graal/clj/skylobby/core.clj:43:3: info: Unused value
it must be something weird with my setup
#2022-10-2017:50borkdudeI'll clone your repo#2022-10-2018:05borkdudeIt does seem to be related to the config, when I move it aside the warning disappears. Looking further#2022-10-2018:09borkdudeoh yikes: .clj-kondo/cnuernber/dtype-next/taoensso/nippy.clj#2022-10-2018:09borkdudeIt seems that dtype-next provides a config for nippy, that's not how things should work :)#2022-10-2018:10borkdudeyes, it's related to that one#2022-10-2018:14borkdudehttps://github.com/cnuernber/dtype-next/issues/67#2022-10-2018:15borkdudebut then again, I think it's also probably better to ignore unused values generated by macros#2022-10-2018:15borkdudeso I'll check if there's a fix for that as well#2022-10-2018:20skynetoh, I should probably fix that and gitignore those other files in .clj-kondo right? I've started using this .gitignore in .clj-kondo folder on new projects:
*
!.gitignore
!config.edn
#2022-10-2018:30borkdudeit's ok to keep that config in .clj-kondo in source control#2022-10-2018:30borkdudebut dtype should just not include config for other libs#2022-10-2018:34skynetI see, thanks for looking into this so deeply!#2022-10-2018:49borkdudeWhen I change the dtype next config for extend-freeze to this:#2022-10-2018:49borkdude
(defmacro extend-freeze
  [_dt _kwd argvec & code]
  (let [[buf-var out-var] argvec]
    `(let [~buf-var 1
           ~out-var 2]
       ;; (type ~dt)
       
#2022-10-2018:49borkdudeThen it works as expected, since I ignored the dt argument (which is the File symbol)#2022-10-2013:20alekszelarkIs it possible to switch linting off for a particular file via namespace local configuration?#2022-10-2014:24borkdudeYou can selectively witch off linters in the metadata or you can just exclude the whole file in the :output {:exclude-files ...} config#2022-10-2014:25alekszelarkThanks#2022-10-2211:38borkdudeClj-kondo configs clj-kondo https://github.com/clj-kondo/configs A repository with clj-kondo configurations for libraries, as dependencies#2022-10-2211:53borkdude@alex.sheluchin I think we could add a dependency to that project with community aliases instead of building them into clj-kondo, like you requested. This seems more flexible#2022-10-2211:55borkdudeSo then you can add io.github.clj-kondo/config-bbatsov-clojure-style-guide to your deps and it will "just work"#2022-10-2211:55borkdudeI see @seancorfield also accepted a PR in that repo. Do you think that would be a good idea?#2022-10-2214:05sheluchin@U04V15CAJ Thank you! I think this is a fine approach for my use case. @UEENNMX0T raised a concern about using it in this way when installing clj-kondo as a bin rather than a project dep. Will a bin kondo not pick up on configs installed this way? I'm not sure I fully understand the difficulty there.#2022-10-2214:06borkdudethere is no difference between binary or JVM clj-kondo#2022-10-2216:47seancorfieldI think an automated checker for the style guide would be awesome, if it's possible.#2022-10-2218:31borkdude@seancorfield @alex.sheluchin OK, you can try to add:
io.github.clj-kondo/config-bbatsov-clojure-style-guide-aliases {:mvn/version "0.1.1"}
to your project dependencies and then restart your clojure-lsp, or run: clj-kondo --lint $(clojure -Spath) --dependencies --skip-lint --copy-configs and then you should get a warning like this:
#2022-10-2218:32borkdudeI noticed that Alex uses jio a lot for so I think there will never be 100% consensus about these things, I'd rather leave it as an optional library than baking it in#2022-10-2218:33borkdudeThe library comes from here: https://github.com/clj-kondo/configs/tree/main/configs/bbatsov/clojure-style-guide-aliases If you want to provide more configurations for other libraries that you don't manage yourself, then this is the place to do so, if the original maintainer doesn't want to have it in their repo#2022-10-2218:38seancorfieldNice! I'll take a look at that when I get back to work on Monday.#2022-10-2218:42sheluchinThanks for the instruction, @U04V15CAJ. I'll probably have time to try it tomorrow. I'm planning on showing a breakdown of aliases per namespace so maybe that will help promote a consensus, but it'll probably never be 100%. That's okay, choice is good :man-shrugging:#2022-10-2218:45seancorfieldWe only have a few standard aliases at work, for third party libs (we have quite a few for our own nses):
clojure.data.json json
    clojure.spec.alpha s
    clojure.string str
    com.stuartsierra.component component
    exoscale.coax c
    next.jdbc jdbc, next.jdbc.result-set rs, next.jdbc.sql sql
    ring.util.response resp
#2022-10-2219:45borkdudeOf course you can configure your own with :consistent-alias as well#2022-10-2222:48seancorfieldAnd that would override the style guide ones?
:linters
 {:consistent-alias
  {:aliases
☝️:skin-tone-2: is the fragment above what I posted.
#2022-10-2306:56borkdudeYes, your own would override but with merging #2022-10-2417:35sheluchin@U04V15CAJ works nice 👍 thank you. I guess I can close https://github.com/clj-kondo/clj-kondo/issues/1839 as completed?#2022-10-2417:54borkdudeok, maybe make a comment in there that this is the solution we landed on#2022-10-2417:55borkdudeand then close it#2022-10-2418:21sheluchindone and done. ty sir#2022-10-2516:41seancorfieldSeems to work nicely -- thanks! I was a bit surprised that clojure.data.json wasn't aliased to json but it isn't in the guide (only because cheshire.core is aliased to json lower down and I didn't want to introduce a conflict when I did that).#2022-10-2218:31borkdude@seancorfield @alex.sheluchin OK, you can try to add:
io.github.clj-kondo/config-bbatsov-clojure-style-guide-aliases {:mvn/version "0.1.1"}
to your project dependencies and then restart your clojure-lsp, or run: clj-kondo --lint $(clojure -Spath) --dependencies --skip-lint --copy-configs and then you should get a warning like this:
#2022-10-2319:39borkdudeAdded a config for nippy extend-freeze and extend-thaw to https://github.com/clj-kondo/configs#2022-10-2406:03robert-stuttaford@borkdude looks like there may be a false positive for unused value when checking mutative transient calls?
src/cognician/base/coll.cljc:151:17: warning: Unused value
src/cognician/base/coll.cljc:162:16: warning: Unused value
(defn distinct-by
  "Keeps items which have distinct `(key-fn item)` results. Not lazy"
  ([key-fn]
   (fn [rf]
     (let [^clojure.lang.ATransientSet seen (transient #{})]
       (fn
         ([] (rf))
         ([result] (rf result))
         ([result input]
          (let [key (key-fn input)]
            (if (.contains seen key)
              result
              (do
                (conj! seen key) ;; <----- here
                (rf result input)))))))))
  ([key-fn coll]
   (let [^clojure.lang.ATransientSet seen (transient #{})]
     (persistent!
      (reduce
       (fn [res item]
         (let [key (key-fn item)]
           (if (.contains seen key)
             res
             (do
               (conj! seen key) ;; <----- here
               (conj! res item)))))
       (transient []) coll)))))
#2022-10-2406:25hiredmanThat is correctly flagged, it is an example of "bashing in place" which the transient docs say not to do#2022-10-2406:29hiredmanThe transient mutating operations all sometimes return a new object and sometimes mutate the existing object, so you cannot ignore the return value#2022-10-2407:49robert-stuttafordfascinating, TIL, thank you!#2022-10-2410:56Noah BogartThis is the whole reason for volatile! to exist, in fact#2022-10-2410:58borkdudeNot really, volatile is just a more performant atom without concurrency safety https://clojure.atlassian.net/browse/CLJ-1512#2022-10-2412:38Noah BogartMaybe I wasn’t clear enough. I don’t mean replacing stateful transients but acting as transducer state management (as demonstrated in your link). Robert’s transducer above is using transients to hold transducer internal state and that is the domain of volatile!.#2022-10-2412:39borkdudeIn this case I would use loop instead of volatile!#2022-10-2412:40Noah BogartIn a transducer?#2022-10-2412:40borkdudeoh right, yeah, not there#2022-10-2413:19robert-stuttafordTIL#2022-10-2413:28borkdudeThe problem seems to be manifesting with transient of map more than anything else though:
user=> (let [t (transient #{})] (doseq [i (range 10000)] (conj! t i)) (count (persistent! t)))
10000
user=> (let [t (transient {})] (doseq [i (range 10000)] (conj! t [i i])) (count (persistent! t)))
8
#2022-10-2416:36hiredmanusing transients not according to how all the docs say they can be used is less likely to lead to an observable bug with sets, but is still ignoring the docs#2022-10-2416:38borkdudeI do agree (and this is the main reason we now have :unused-value actually), but just to be clear, which docs are you referring to - the docstrings of transient and conj! or the Clojure website?#2022-10-2416:38hiredmanthe clojure website#2022-10-2416:39borkdudeI think the exclamation marks send people in the wrong direction, thinking that it's bashing in place, so the return value doesn't matter that much#2022-10-2416:39borkdudePerhaps the docstrings of transient related functions could emphasize this more#2022-10-2416:42hiredmanor a linter that marks using transients as an error until the user pinky swears that they have read the docs#2022-10-2416:43borkdudeor just :unused-value, and then they'll ask here and have "the conversation" on transients :)#2022-10-2419:48robert-stuttaford"the conversation" 😂#2022-10-2417:10dchelimskyFeature request (or "please show me where the existing feature that I can't find is" request): option to check that every file ends in a single newline. WDYT?#2022-10-2417:54borkdude@dchelimsky All available linters are here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md All available configuration options are here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md Your request isn't in there yet, but is very similar to the :line-length linter, implementation-wise https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#line-length Feel free to post an issue and if you want I could guide you how to implement it as well#2022-10-2419:50dchelimsky@borkdude it's been suggested that this should be a cljfmt thing. WDYT?#2022-10-2420:03borkdudeI'm fine with both#2022-10-2514:52alekszelarkclj-kondo complains about an unresolved symbol in s/def . Same works perfect with s/fdef . What a recommended way to resolve it?#2022-10-2514:53borkdude@zelark You should probably use a keyword there#2022-10-2514:54borkdude
(s/def ::whatever (s/any? *))
#2022-10-2514:56alekszelarkyeah, a keyword works, but with a symbol it’s also a valid expression. We use it to refer to the same spec for a fn in few places.#2022-10-2514:57borkdudeHmm ok, this needs to be fixed in clj-kondo then. Issue welcome#2022-10-2514:59alekszelarkThanks, my colleague will do#2022-10-2515:01borkdudecool#2022-10-2519:19vemvI have a dep management issue when running lein-clj-kondo on a particularly contrived project. These are the relevant bits:
Syntax error compiling at (clojure/tools/reader/edn.clj:1:1).
	at clojure.lang.Compiler.load(Compiler.java:7652)
	at clojure.lang.RT.loadResourceScript(RT.java:381)
	at clojure.lang.RT.loadResourceScript(RT.java:372)
	at clojure.lang.RT.load(RT.java:459)
	at clojure.lang.RT.load(RT.java:424)
	at clojure.core$load$fn__6856.invoke(core.clj:6115)
	at clojure.core$load.invokeStatic(core.clj:6114)
	at clojure.core$load.doInvoke(core.clj:6098)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invokeStatic(core.clj:5897)
	at clojure.core$load_one.invoke(core.clj:5892)
	at clojure.core$load_lib$fn__6796.invoke(core.clj:5937)
	at clojure.core$load_lib.invokeStatic(core.clj:5936)
	at clojure.core$load_lib.doInvoke(core.clj:5917)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:669)
	at clojure.core$load_libs.invokeStatic(core.clj:5974)
	at clojure.core$load_libs.doInvoke(core.clj:5958)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:669)
	at clojure.core$require.invokeStatic(core.clj:5996)
	at clojure.core$require.doInvoke(core.clj:5996)
	at clojure.lang.RestFn.invoke(RestFn.java:619)
	at edamame.impl.parser$eval12811$loading__6737__auto____12812.invoke(parser.cljc:1)
	at edamame.impl.parser$eval12811.invokeStatic(parser.cljc:1)
	at edamame.impl.parser$eval12811.invoke(parser.cljc:1)

...

Caused by: java.lang.IllegalAccessError: reader-error does not exist
	at clojure.core$refer.invokeStatic(core.clj:4237)
I tried bumping tools.reader to no avail. Does it ring a bell? (doesn't look too hard - will keep trying in the meantime!)
#2022-10-2519:21Alex Miller (Clojure team)this might be a tools.reader version conflict with the version aot'ed into clojurescript#2022-10-2519:21borkdudethe vendored version in CLJS uses a namespace prefix, I think?#2022-10-2519:22Alex Miller (Clojure team)it does now#2022-10-2519:22Alex Miller (Clojure team)but it didn't in older versions#2022-10-2519:22borkdudeWhat could also be the case is that an older tools reader is pulled in than what edamame depends on https://github.com/clojure/tools.reader/blob/d721510c37eb4d28247dd90c07c3c9a7dc3820ed/src/main/cljs/cljs/tools/reader/impl/errors.cljs#L39#2022-10-2519:47vemvalthough the clojurescript bump thing was a good lead (and something I'll try to keep in my head) finally it was a matter of adding this exclusion: [lein-asset-minifier "0.4.6" :exclusions [org.clojure/tools.reader]] legacy projects / plugins. 🌀#2022-10-2520:13Noah Bogartany interest in a linter that checks for (-> some-obj (. interopCall) (. interopCall2) (. interopCall3))? It would look for thread-first macros that all have interop calls and suggest using (.. some-obj (interopCall) (interopCall2) (interopCall3)) instead#2022-10-2520:15borkdudeNot interested - after macroexpansion this is all the same?#2022-10-2520:16borkdudeI'm more interested in the dynamic var linter 😉#2022-10-2520:16Noah Bogartheh I started work on that last night but don't have much free time at the moment.#2022-10-2520:17vemvsilly observation but -> is so perfect :star-struck: there's also (-> some-obj .interopCall .interopCall2 .interopCall3) I'd like the versatility of -> - for misc ops, interop, data access, math sometimes. All with the same keystrokes (I have a life-changing snippet that expands - to (-> $1)#2022-10-2520:17Noah BogartI prefer to be consistent in these kidns of things, and like nesting a do block inside of a when, seems like "use the semantically correct tool"#2022-10-2520:17borkdudeyes, I like ->#2022-10-2520:18borkdudedo is different, a redundant do clears up nesting and thus noise, but -> vs .. doesn't reduce any noise imo#2022-10-2520:18Noah BogartSure. If you don't want it, then I won't open an issue for it.#2022-10-2520:22Noah BogartHave you thought about qualifying/namespacing the linter keywords? :style/consistent-alias, :lint/loop-without-recur, :syntax/duplicate-map-key, :performance/redundant-fn-wrapper etc#2022-10-2520:24Noah BogartOn the one hand, it would require some sort of "conversion" step to maintain backwards compatibility, but on the other hand, it would make space for things like "disable all style linters" and increase the meaning of each linter name#2022-10-2520:28borkdudeI've considered it but not adopted it#2022-10-2520:30Noah BogartWell, I'm willing to help if you decide to go for it#2022-10-2520:36borkdudeI'd rather see work happening elsewhere#2022-10-2520:37Noah Bogartsadly, I am driven entirely by whim 😉#2022-10-2522:27dpsuttonIs there an alias for duplicate test names? Every now and then I end up with (deftest foo …) and then another (deftest foo …) in the same file and of course only one will run. Doesn’t take too long to figure out so no huge need for it. Just would be a nice quality of life perhaps#2022-10-2522:48borkdudeThis should result in a redefined var warning #2022-10-2522:48dpsuttonOh lovely. I’ll double check#2022-10-2602:51Noah BogartWhat does lift-meta-content2 do?#2022-10-2711:57roman01la@borkdude Hey, thanks for the heads up on analysis stuff! How can I tell clj-kondo to produce full analysis AST? What I'm seeing right now is only var definitions w/o body AST#2022-10-2711:59borkdudeHey! Yes, re-iterating my comment on Reddit: What you get from the analysis data is just data, no AST. But you can match this data on location on whatever AST structure you produce using rewrite-clj.#2022-10-2712:00borkdudeE.g. getting the fully qualified var name or whether something is a local, etc, you should be able to look up in the analysis data#2022-10-2712:04roman01laOh, I see, I thought there's something new I've missed from clj-kondo. This approach doesn't seem suitable for me. I find it more straightforward to have a full AST map at hand right away, as someone who's not familiar with clj-kondo internals.#2022-10-2712:07borkdudeYes, I get that. But to produce such a structure, you can use the clj-kondo analysis. Else you would have to write your static analysis yourself#2022-10-2712:07borkdudeSo while walking the raw rewrite-clj structure, you can look into the clj-kondo analysis if some symbol is a local or var, then add that data and produce your AST.#2022-10-2712:10roman01laHmmm, that makes sense. I can see var defs in analysis output, but not local vars. Is there a config switch for that or something?#2022-10-2712:11borkdudeyes: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#extra-analysis#2022-10-2712:12roman01lanice! I thought :analysis true would include everything#2022-10-2712:12borkdudelocals and keywords is a lot of data, this is why it wasn't included by default#2022-10-2712:17roman01laok, I'm seeing the data now. Still it means depending on clj-kondo would mean splitting the analyzer in two pieces and parsing inputs twice: to get vars data from clj-kondo and produce AST for everything else myself, which doesn't feel solid to me.#2022-10-2712:20borkdudeThis approach is what several tools are doing, clojure-lsp being one of them. Works quite well. Yes, if you use a tool do to analysis, it becomes a dependency. Parsing the code twice isn't really a problem, it's only a small fraction of the total time taken.#2022-10-2712:21borkdudeYou also benefit from clj-kondo hooks that people write for their custom macros#2022-10-2712:22borkdudeWhen clojure-lsp adopted clj-kondo we considering sharing the AST but it wasn't worth the trouble#2022-10-2712:22roman01laGood point about macros!#2022-10-2720:30Eric DvorsakIs it feasible for clj-kondo to detect namespaces with mount/defstate that are not required before mount/start is called (I mean does it has enough context to do such checks)? that leads to some nasty NPEs in packaged jars#2022-10-3019:42Matthew TwomeyNot positive if this is the best channel, but I’ve run into a strangeness with Kondo (via LSP) in Emacs. I’m editing a babashka script and kondo appear to work fine with one exception: I have several requires in my file, always using the :as [thing] qualifier. All of my references lint ok with the exception of “io.avisio.ansi” (`(require [io.aviso.ansi :as ansi-colors])`). It functions fine in my code (e.g. (str (ansi-colors/bold-white "Hi, I'm bold!")) , however I can’t get rid of “unresolved var” linting warnings on every use of ansi-colors/*** in my code. All my other requires lint just fine. I believe I’ve deleted all caches everywhere and this still happens. Has anyone run into anything similar?#2022-10-3020:03hiredmanIt is likely to due to how io.aviso.ansi defines those names#2022-10-3020:04hiredmanhttps://github.com/AvisoNovate/pretty/blob/master/src/io/aviso/ansi.clj#L95#2022-10-3020:04Matthew Twomeyoooh#2022-10-3020:04hiredmanKondo's static analysis cannot understand that, so it doesn't know those names are defined there#2022-10-3020:05Matthew Twomeywell shoot. Ok - well at least I’m not crazy 🙂#2022-10-3020:05Matthew TwomeyThanks sir#2022-10-3020:13borkdudeYou can exclude that namespace from unresolved var:
:unresolved-var {:exclude [io.aviso.ansi]}
#2022-10-3020:13borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-var#2022-10-3020:14Matthew TwomeyYeah I’ll probably give that a shot just to clean it up a bit. Thanks.#2022-10-3020:14Matthew TwomeyThis is good to know as I start to develop my own libs to keep them linter friendly.#2022-10-3020:19borkdudeIf you are using clojure-lsp, then you could also generate stubs: https://clojure-lsp.io/settings/#stub-generation which emit (declare ..) or (def ...) just for the purpose linting/completions#2022-10-3020:24borkdudeIt uses this library: https://github.com/clj-easy/stub#2022-10-3100:33Matthew TwomeyOooh - I hadn’t heard of that (yes I’m using clojure-lsp), will take a look thanks.#2022-10-3102:30Matthew Twomey@U04V15CAJ Stubs worked a treat. Thansk!#2022-10-3019:46Matthew TwomeyThis also is preventing auto-suggestion / completion (which is my primary pain really).
#2022-10-3115:08grahamcarlyleI'm using clj-kondo with the clj-extras plugin in intellij. Does anyone know if there is a way to suppress the built-in Cursive inspection warnings that are covered by the clj-extras inspection's (absence of) warning? I guess I could just disable all Cursive's inspections, such as "unresolved var", but I worry there may be valid warnings that I would lose that clj-kondo would not warn about.#2022-10-3115:34brcostaThrough the plugin currently there’s no way to do this automatically. You can pick and choose in the inspection settings to see what fits you workload#2022-10-3115:35brcostaCan’t remember when I did it but mine is like this today:#2022-10-3115:40grahamcarlyleThanks 👍 are those disabled because you think that clj-kondo covers them from your experience?#2022-10-3115:44brcostayep 🙂#2022-10-3115:51borkdude🙏#2022-10-3116:29grahamcarlylei guess only "unresolved symbol" is a potential false positive from cursive because it doesn't know about macros via the clj-kondo config. So maybe double reporting a problem isn't much of an issue, or @UQTHDKJ8J do you know if there are other potential false positives from Cursive?#2022-10-3123:10brcostaI don’t know if I understood the question, but as we use highly custom clj-kondo config in our projects, everything just works really well#2022-11-0122:29steveb8nQ: I just started using clj-kondo. it’s warning me about adding docstrings in deftest forms. Cursive interprets these as docstrings so I’m trying to figure out my path forward. Do I block clj-kondo from checking this or figure out a more idiomatic way to add docstrings to tests. what is the idiom?#2022-11-0122:30steveb8nnot really a kondo question but arises thanks to it’s effectiveness#2022-11-0122:31borkdude> it’s warning me about adding docstrings in deftest forms I've never seen this...#2022-11-0122:33borkdudeDo you have a better repro than this one?#2022-11-0122:35borkdudeOr do you mean: how do I add docstrings to tests? I think like this:
(t/deftest ^{:doc "Hello"} foo
  1)
#2022-11-0122:35borkdudeE.g. this:
(t/deftest foo
  "Foo"
  1)
Doesn't add a docstring to #'foo - you can see that when writing (meta #'foo)
#2022-11-0122:50steveb8ngreat. I was hoping it would be something like that. I’ll try and report back#2022-11-0123:59steveb8ngreat. the inline meta you show above works for Kondo and Cursive. Thanks!#2022-11-0123:59steveb8nsleep well!#2022-11-0209:04borkdudeAnd maybe more importantly: it works for Clojure itself :)#2022-11-0209:43steveb8nOh yeah, that too 😂#2022-11-0211:53borkdudeChangelogs for release later today: https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#unreleased Please give it a spin on your repo before release, as a sanity check.#2022-11-0215:57Noah Bogart
$ ~/Downloads/clj-kondo-2022.10.15-SNAPSHOT-linux-amd64/clj-kondo --parallel --cache false --lint src/ dev/ test/
linting took 12783ms, errors: 0, warnings: 0
lookin good to me (using the artifact from https://github.com/clj-kondo/clj-kondo/commit/7798e4ecbdf65495f2bf25f58df2d2ba0540fc8f)
#2022-11-0215:59borkdudethanks!#2022-11-0219:49borkdudehttps://clojurians.slack.com/archives/C06MAR553/p1667410241524099#2022-11-0220:58Sam Ritchiehey all! I am trying to get the linter to totally ignore arguments to a macro, since I haven’t yet written a hook, and thought this might work:
{:lint-as {jsxgraph.clerk-ui/cljs clojure.core/comment}}
#2022-11-0220:59Sam Ritchieno dice. any advice on why this wouldn’t work, or if there is a :lint-as solution here? or if I should just write a hook that ignores everything#2022-11-0221:14borkdude@sritchie09 clj-kondo doesn't just ignore anything in comment forms since it's quite useful to have linting in your comment forms. You can tweak what linting you get in comment forms using :config-in-comment - similarly you can tweak what config you get in calls to your macro with :config-in-call See docs https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#override-config-in-comment-forms#2022-11-0221:52Sam Ritchiethank you!#2022-11-0221:54Sam Ritchieactually @borkdude maybe there is a way to do this without a hook. This macro should emit nothing for clj , and everything passed to it for cljs; is there some default way to specify this?#2022-11-0221:56borkdudeI'll get back to you tomorrow 💤#2022-11-0314:44borkdudeI'm going to look at this in 20 minutes#2022-11-0315:07Sam Ritchie@borkdude if you haven’t looked, I am now past this;#2022-11-0315:08Sam RitchieI figured out how to skip compilation of notebooks, so now that macro only runs on the JS side and can’t do any JS linting anyway, so I will go with the ignore style that you showed me. thank you!#2022-11-0315:22borkdudeok :)#2022-11-0314:58lassemaattawould it be technically possible for clj-kondo to detect if ^{:some-metadata "foo} was being applied to an unsuitable form?#2022-11-0314:59borkdudetechnically yes :)#2022-11-0314:59lassemaattafor example I was looking at some reagent code such as ^{:key id} (if foo? [:div] [:span]), which according to my very limited understanding of metadata is incorrect#2022-11-0315:00borkdudeit's not incorrect as in, the clojure reader will fail, but the metadata is discarded since if doesn't do anything with it. you should use with-meta here#2022-11-0315:03lassemaattaindeed. But it seems like it's a relatively common mistake to make, I think I've seen it a couple of times because it's easy to assume it applies to the resulting value at runtime (like with-meta). Sure would be nice to notice problems like that without looking at the react warnings in the js/console 😉#2022-11-0315:04lassemaattabut I have no idea is it possible to reliably detect when the metadata is being ignored#2022-11-0315:23borkdudein general it's not really something you can detect that is "wrong" since the macro (or special form) might do something with this metadata#2022-11-0315:24borkdudebut e.g. ^{:foo} 1 is always wrong, since it's a reader error#2022-11-0318:17DumchIs there some helper function to get a value by key from the map-node?#2022-11-0318:23borkdude@arturdumchev Currently there's not such a helper#2022-11-0318:30DumchI will check on weekends if there is a good solution to add one and maybe come up with the pr#2022-11-0318:31borkdudeLet's first discuss if this is a common enough problem to add something for#2022-11-0318:33DumchMy case: macro gets a map as a param. I have to get nodes from this map to use with-meta further#2022-11-0318:36borkdudecan you describe your use case further? example call of the macro for example? why do you need to read from the map?#2022-11-0318:37DumchThe codebase I am working now has a lot of macro like:
(macro-that-will-creat-several-functions
  {:get-function "name-of-the-get-fn"
   :set-funtion  "name-of-the-set-fn"
   :this-will-be-used-so-I-need-to-tell-clj-kondo-that-this-value-is-used pool-that-will-be-used-inside})
#2022-11-0318:38DumchMaybe better way would be to avoid having a map here and just use keys and values#2022-11-0318:39borkduderight#2022-11-0318:40borkdudeI have a library with some common operations for rewrite-clj nodes here https://github.com/borkdude/rewrite-edn/blob/80f246139b1a43b6f2cbab329521d060ee7c1b7b/src/borkdude/rewrite_edn/impl.cljc#L118#2022-11-0318:42borkdudebut since clj-kondo nodes don't have whitespace, it's relatively easy to transform them in a map:
(let [children (:children map)
      ks (take-nth 2 children)
      ks (map api/sexpr ks)
      vs (take-nth 2 (rest children))]
  (zipmap ks vs))
  
#2022-11-0318:42borkdudethere you have the key s-expressions to nodes#2022-11-0318:43Dumchthank you!#2022-11-0520:42borkdudeI just pushed a type checking improvement to clj-kondo. I'd appreciate it if this could get some early testing. https://twitter.com/borkdude/status/1588493830961393664 are some examples of what is improved#2022-11-0607:18danielcomptonIs there a way to configure clj-kondo to disable the redundant expression linter just inside Midje fact /`facts`?#2022-11-0607:19danielcompton
(facts "about tests"
  (fact "math"
    (let [res {}]
      (:status res) => 204
      (+ 1 1) => 2)))
#2022-11-0607:56borkdudeYou could also try lint as testing ?#2022-11-0607:57borkdudeElse try config in call, see config.md #2022-11-0608:09borkdudeSorry for the brief answer, I’ll repost here when I’m at the kbd #2022-11-0608:38borkdudeOh sorry, I didn't see the screenshot, so testing won't work here. Try :config-in-call#2022-11-0608:39borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#config-in-call#2022-11-0610:35borkdudecc @UKFSJSM38 I think you contributed to the config for this lib right#2022-11-0613:01ericdalloYeah, I added some hooks and some flaky fixes, do you think that one could go to the lib exported config as well?#2022-11-0613:02borkdudeI think so, but it would be good to test it :) The :redundant-expression linter got merged with :unused-value recently. It seems that @U051KLSJF is still on an older version of kondo.#2022-11-0618:09danielcomptonThanks! I’ll try make a docs patch, I looked at the table of contents on the config but that one didn’t pop out to me. #2022-11-0813:06xificurCin photon we have p/server and p/client blocks. They map to arbitrary cases but let's say it is static for now and server=clj, client=cljs. How could I teach kondo to analyze code in a server block as clj only and client as cljs only? Right now kondo reports a lot of false warnings, rendering it very hard to use#2022-11-0813:07xificurC
(p/server (clj-call-here (p/client (cljs-call-here))))
#2022-11-0813:08borkdudeis this with in a .cljc file? it might be possible to do this with an analyze-call hook where you inspect the :lang key.#2022-11-0813:29xificurCyes, it is in cljc files. The platform is "colored" in code through the p/server and p/client calls, there are no reader conditionals to help out in the static analysis#2022-11-0813:29borkdudeok, I think a hook might help here#2022-11-0813:31borkdudea hook gets these two arguments: https://github.com/clj-kondo/clj-kondo/blob/addcf68bbf0be511f5aaa1841d856ca2e9b2a39a/src/clj_kondo/impl/analyzer.clj#L1967-L1968#2022-11-0813:32borkdudewhen linting a .cljc file, the hook will be called twice: once with :lang :clj and once with :lang :cljs#2022-11-0813:32borkdudeyou can then ignore the part that is only relevant to the language and pass back the rest#2022-11-0813:33xificurCby ignore you mean like return nil?#2022-11-0813:34borkdudereturn a new node with the irrelevant part stripped out#2022-11-0813:34borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md https://github.com/clj-kondo/hooks-workshop-clojured-2022#2022-11-0813:37borkdudeSo what you can do is make a hook for p/client and when :lang :clj then you return a nil node for example#2022-11-0813:37borkdudebut when :lang :cljs you return the original node#2022-11-0813:37xificurCI'll take a look, thanks. I wonder how tricky will this get, since the colors can nest. I can't e.g. stop cljs analysis when I see a p/server since there might be another p/client call, arbitrarily deep#2022-11-0813:37borkdudeis there a reason why this system doesn't use reader conditionals?#2022-11-0813:38borkdudeclerk has a similar setup but there the CLJS bits are in quotes#2022-11-0813:38borkdude'(fn [x] ...)#2022-11-0813:48xificurCyes, because that's not what happens in https://hyperfiddle.notion.site/Reactive-Clojure-You-don-t-need-a-web-framework-you-need-a-web-language-44b5bfa526be4af282863f34fa1cfffc. It's a whole-program compiler that emits 2 programs and manages the network layer between them. As I think about it this is trickier than it looks, e.g.
(p/server
  (let [x 1]
    (p/client (inc x)))
is valid code where the client will receive the value of x over the wire. If I was to disregard the let block for cljs the client snippet would complain about unbound x.
#2022-11-0813:49xificurCAlso, the server/client needn't be clj/cljs, in tests it's often clj/clj, it's based on startup configuration#2022-11-0813:49xificurCThanks for your input!#2022-11-0814:01borkdudeyou could also disable some things like unresolved symbols in p/client#2022-11-0814:01borkdudeusing :config-in-call#2022-11-0814:02borkdudeor :unused-binding etc#2022-11-0814:27dpsuttonGetting an unused binding warning on definterface which seems wrong.
❯ echo "(definterface Foo (foo [x]) (bar [x]))" | clj-kondo --lint -
<stdin>:1:35: warning: unused binding x
linting took 12ms, errors: 0, warnings: 1
the warning is on the (bar [x]) form. Is this a known issue?
#2022-11-0814:31borkdudeSeems so. Issue welcome. Workaround:
#_{:clj-kondo/ignore [:unused-binding]}
(definterface Foo
  (foo [x y])
  (bar [x])
  (dude [z]))
#2022-11-0814:31dpsuttonmaking an issue now. thanks#2022-11-0817:25Ben LiebermanI wouldn't be surprised if this is user error as I'm not all that experienced with protocols yet, but I'm getting an unused-public-var on my method signatures despite providing an implementation of these methods through extend-protocol in the same ns#2022-11-0817:59borkdudecc @UKFSJSM38#2022-11-0818:02ericdalloSounds like a bug, could you paste a simple repro code here?#2022-11-0818:06Ben Lieberman
(defprotocol Stats
  (get-stats [this profile])
  (compute-advanced-stats [this]))

(extend-protocol Stats
  PlayerStats
  (get-stats [this profile] (assoc profile :stats this))
  (compute-advanced-stats [this] this))
#2022-11-0818:07Ben LiebermanI have another protocol that I implement directly on a record type and it doesn't give this lint#2022-11-0818:10ericdalloYeah, it seems it's a bug, please open on clojure-lsp, not sure if it's something to be fixed on clj-kondo but we can discuss in the issue#2022-11-0818:10Ben LiebermanYeah sorry about the wrong channel, I saw the lint and forged ahead assuming it was clj-kondo and not clojure-lsp 😅#2022-11-0818:25ericdallonp, that is common, that is the only linter that is done by clojure-lsp using clj-kondo analysis#2022-11-0818:25ericdalloso the bug may be on both in the end anyway 😂#2022-11-0912:15ericdallo@U03QBKTVA0N I pushed to https://github.com/clojure-lsp/clojure-lsp/tree/fix-unused-public-var-for-protocols which fixes it, but it needs more manual and unit tests as it touches critical code, maybe you could give it a try? Just cloning the branch and bb debug-cli#2022-11-0915:08Ben LiebermanSure, I'll give that a go over lunch and let you know the results. Thanks for quick turnaround @UKFSJSM38#2022-11-0821:22borkdude#2022-11-0921:35sheluchinThanks for cross posting!#2022-11-0915:32Alex Miller (Clojure team)@borkdude btw, re your https://twitter.com/borkdude/status/1589951843991683073 on :refer :all, that's actually a warning, not an error, in Clojure 1.12.0-alpha1 due to the changes in var interning#2022-11-0915:36Alex Miller (Clojure team)this is actually similar to the issue we saw with adding clojure.core/abs in 1.11 (but that's a little more special because clojure.core is auto-referred)#2022-11-0915:39borkdude@alexmiller Awesome!#2022-11-0922:01pezHow do I disable all linting for a file from within the file? This doesn't work:
(ns foo
  {:clj-kondo/config ^:replace {:linters {}}})
Can it be done? 😃
#2022-11-0922:04borkdudeThis can't currently be done from within a file#2022-11-0923:26seancorfield@borkdude On a related topic, can ns metadata provide :lint-as config for macros in that ns? I've not been able to get that to work...#2022-11-0923:27borkdudeyes, that should work but you have to use the quote on the config
{:clj-kondo/config '{:lint-as {foo.bar/baz ...}}}
#2022-11-0923:28borkdudein fact I used it yesterday for this example: https://gist.github.com/borkdude/1fc2bd73c77d094fb0577c9caf9684b3#2022-11-1000:36seancorfieldAnd that foo.bar/baz is how to refer to a macro baz in the same file, i.e., where the ns is (ns foo.bar ..)?#2022-11-1008:01borkdudeCan you give a full example, just to make sure we’re taking about the same thing?#2022-11-1017:10seancorfieldI found the non-working example and futzed with it a bit and it starting working. Two things seemed to be working against me: • I had #:clj-kondo{:config ..} • I had :lint-as '{...} Once I changed the format to {:clj-kondo/config '{:lint-as {..}}} it worked -- i.e., switched away from the namespaced-map format and moved the quote out to the whole :clj-kondo/config value instead of just the :lint-as value.#2022-11-1017:11borkdudegreat, yes, this is the expected format. The reason it works like this is that clj-kondo sees this as a rewrite-clj node, not as plain EDN#2022-11-1017:11borkdudeand writing quotes in unexpected places gets you EDN like this: {(quote foo) bar} etc which is hard to parse#2022-11-1017:12seancorfieldAh, I didn't realize it was so sensitive to structure -- I'd assumed Clojure-equivalence in syntax.#2022-11-1017:12borkdudeit's not evaluated#2022-11-1017:13seancorfieldRight, but I thought that was reader-equivalent.#2022-11-1017:13seancorfieldI can see now that it is subtly different 🙂#2022-11-1017:13borkdudeIt's documented here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#metadata-config (I don't mean that as RTFM, just FYI ;))#2022-11-1017:14seancorfieldWell, if I'd read that caveat, I would have known! :rolling_on_the_floor_laughing: Thank you!#2022-11-1001:43Jungin KwonI am setting up clj-kondo for https://github.com/Engelberg/better-cond. I keep getting ::Unresolved var: b/cond error even after copying configs.#2022-11-1001:44Jungin KwonWhat else do I need to configure?#2022-11-1007:52borkdudeYou need to also lint the better cond dependency if you have those configs in place #2022-11-1007:53borkdudeRepro as clonable repo welcome, this is a better way to talk about the same thing. #2022-11-1016:31Daniel GersonThought I'd mention that not-empty? warning although appropriate for sequences isn't for (-> #{} empty? not) (Edit: Please disregard :man-facepalming: )#2022-11-1017:05imreInteresting. Why?#2022-11-1017:05imre
(mapv
 #(= (boolean (seq %))
     (not (empty? %)))
 [[]
  [1]
  #{}
  #{1}])
=> [true true true true]
#2022-11-1017:06imreor perhaps this is a different warning I'm thinking about?#2022-11-1017:07imreWhat am I missing?#2022-11-1020:58Daniel Gerson@U08BJGV6E Thanks for double checking me! Did I make a mistake? Apologies if so. Will recheck.#2022-11-1021:00imreDo share what you find!#2022-11-1021:02Daniel GersonI must have used seq? instead of seq ! Sorry all. :man-facepalming:#2022-11-1021:03Daniel GersonOr perhaps even more mixed and matched up than that.#2022-11-1021:09Daniel GersonAs I wasn't paying attention to the question mark, I can't be certain, so not sure of the results I got. Something about my brain associates`not empty?`as a question as it does seq?, where I don't read seq naturally in the same way. laughcry I will learn, thanks again 🙏#2022-11-1021:15Daniel Gerson🏆 for both clj-kondo and the #CHY97NXE2 channel!#2022-11-1109:05BenjaminDoes it make sense that clj-kondo throws "unresolved namespace" for user ? The use case is I setup dev vars in user, then reference them in rich comments in source files. Guess 1 solution is to have the rich comments in the user file instead.#2022-11-1109:40borkdude@benjamin.schwerdtner Just write (require 'user) to solve this. All namespaces must be required prior to use is the rule#2022-11-1109:42borkdudeFor user this might seem a bit silly, but don't know if it's common enough to make an exception for that#2022-11-1110:50mkvlrdoes clj-kondo support colored output on the CLI to differentiate warnings from errors?#2022-11-1110:53borkdudenot currently#2022-11-1110:53borkdudeyou can build your own reporter by just using the EDN output though#2022-11-1112:21ericdalloDoes it make sense to have a linter about files without newlines?#2022-11-1112:21ericdalloI know it's not related to clojure, but it's pretty common to expect linters to check that#2022-11-1112:23ericdalloExample from a github PR I'm reviewing#2022-11-1112:24imre> files without EOF an endless file? 😛#2022-11-1112:24borkdudeDo you mean newline?#2022-11-1112:24imreI do support the idea#2022-11-1112:25ericdalloyep, my bad :p#2022-11-1112:25borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1852#2022-11-1112:25ericdalloOh great!#2022-11-1112:26ericdalloSeems pretty upvoted, so I think there are people thinking the same 🙏#2022-11-1112:49borkdudeyes, would be good for the next iteration#2022-11-1112:30delaguardoI just stumble upon an exception that could be easily detected by clj-kondo but it doesn’t 🙂 After merging I’ve got duplicate symbols in defrecord definition. On the first look It seems easy to add an extra linter to kondo if it sounds interesting 🙏#2022-11-1112:39borkdudeCan you give an example?#2022-11-1112:41delaguardo(defrecord X [y y])#2022-11-1112:41borkdudehmyeah ok, seems like a good lint. this crashes the compiler?#2022-11-1112:42borkdudeyes it does#2022-11-1112:42delaguardoyes, it throws#2022-11-1112:45borkdudesame for deftype, perhaps :duplicate-field {:level :error}#2022-11-1112:45borkdudeissue welcome, optionally followed by PR#2022-11-1113:09delaguardothanks for the confirmation 🙂 I’ll file one#2022-11-1113:18delaguardohttps://github.com/clj-kondo/clj-kondo/issues/1875 done, will make a PR later today (probably 🙂)#2022-11-1115:29Noah Bogartis it possible to get the pre and post map from a function definition in a hook? or do I have to do
(let [children (:children (drop 2 node))
      children (if (api/vector? (first children)) (rest children) children)]
  (if (api/list-node? (first children))
    (->> children
         (filter api/list-node?)
         (map :children)
         (map #(if (api/vector-node? (first %)) (rest %) %))
         (keep #(when (and (api/map-node? (first %)) (next %))
                  (->> (:children (first %))
                       (partition 2)
                       (filter (fn [[k _v]] (and (api/keyword-node? k) (#{:pre :post} (:k k)))))
                       (seq)))))
    (when (and (api/map-node? (first children)) (next children))
      (->> (:children (first children))
           (partition 2)
           (filter (fn [[k _v]] (and (api/keyword-node? k) (#{:pre :post} (:k k)))))
           (seq)))
#2022-11-1209:16borkdudeThere's nothing built-in for this#2022-11-1202:09pfeodrippeClj-kondo support was added to 🎹 Overtone 🎵, bugs were found and sparked https://github.com/overtone/overtone/pull/493, also see https://twitter.com/pfeodrippe/status/1591248247448023041?s=20&amp;t=HyBOP-JCQuICvxd1fLv9Kw (yes, eventually I will be on mastodon or cohost). Overtone has lots of macros, a overtone.linter ns was added which dynamically adds a clj-kondo config (as there are things that are only found at runtime and the config.edn file was huge), we can improve it over time, but it's a good start =D Go make some music, now properly linted#2022-11-1417:45leoiacoviniHello folks, I wanted to get some help to understand how to implement a custom linter a bit tricky using clj-kondo (and if it is possible as a whole). I have a situation where given a macro (lets call it foo here), and a list of forbidden__ vars (qualified with namespaces), I want to check that none of those are being called inside foo, up until this point everything is mostly fine. The biggest problem is: I want to be able to identify also “indirect calls”, that is, if bar is a forbidden__ function, and baz (another function) call bar, then baz should not be allowed to be called too. Example:
(defn bar []
  )

(def baz []
 (bar))

(foo 
 (baz)) ;; This should raise a linter warning/error
I wanted to have this as custom warning on lsp editors and lint runs. Any clues if this sounds feasible, and if so, where should I start looking?
#2022-11-1417:47borkdude@leoiacovini you could possibly lint the direct calls inside the macro using :config-in-call {;discouraged-var {ns/foo true ns/bar true}}#2022-11-1417:53leoiacoviniIt seems to be a start, but creating the dependency graph to trace back indirect calls is still a challenge, right? Just to bring a bit more of color, I am wanting to build a linter to precent blocking call inside core.async go blocks mainly, not sure if this could fit into clj-kondo core as a whole#2022-11-1420:44borkdudeYou could probably do this using clj-kondo as a tool, using it's analysis, but it's hard to implement this as a custom linter that you will use in your editor.#2022-11-1420:44borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#2022-11-1421:32leoiacovini@UKFSJSM38 AFAIK clj-depend integration with clojure-lsp is also made using this approach, any chances of us being able to leverage a similar mechanic?#2022-11-1422:00ericdalloProbably we would need to do something custom using kondo analysis I think, @leoiacovini, recently clojure-lsp added the dump feature, which mostly offer things that clojure-lsp knows about the project including kondo analysis normalized for the project. One idea is to use this on CI and export the data to some kind of datalake where custom tools could use that info and do more smarter findings like your idea.#2022-11-1422:11leoiacoviniWith clj-kondo analysis dump it should be fairly easy to get this recursive search, the thing that I am missing is the capability to give users realtime smart feedbacks in their editors. I am not sure how this would look from a performance perspective though#2022-11-1422:15ericdalloYeah, for that we would probably need something bigger on clojure-lsp or kondo side, where given a bunch of project analysis would do a custom lint. It's like kondo hooks but smarter, since kondo already have all the hooks infrastructure maybe could support something like, a function call that given some project analysis would do a custom lint for a macro.#2022-11-1422:17borkdude@UKFSJSM38 or people could get an lsp hook (interpreted via SCI like clj-kondo hooks) where they have access to the entire in memory data of lsp#2022-11-1422:31ericdalloYes, I'd like to just avoid creating a monster, kondo hooks are already pretty complex for some users, I'd like to avoid having LSP hooks implementing same kondo logic, so it'd be nice to leverage kondo existing hooks with the capacity of just passing analysis which LSP could do, WDYT?#2022-11-1422:32borkdude@UKFSJSM38 yes, that's a nice idea :) the hooks get access to a map and we can pass additional things in that map#2022-11-1422:33ericdalloYes, something like that sounds like a good move#2022-11-1423:35leoiacovinilooks interesting indeed, I tried running clojure-lsp dump but it have me a ~60mb output 🤯 , there is a way to narrow down the scope of it to project only files? (I guess it is recursively getting all classpath data).#2022-11-1423:37ericdalloIt has a filter-keys to just filter keys you are interested, but probably you are not interested on analysis from classpath, only your project, this is easy to make it available, please create a issue so we can discuss the best API for users/what flag to add#2022-11-1502:53skylizeSeems like clojure.test.check.clojure-test/defspec should lint correctly without extra config.#2022-11-1504:26skylizeAlso the spec name gets added to the namespace as a callable function, which should ideally not be considered unresolved. (defspec my-spec ...) (my-spec 20) ; => a quick-check result#2022-11-1505:39seancorfieldHow would clj-kondo know that if you don't tell it how defspec works? (unless it's built-in to clj-kondo which very few libraries are)#2022-11-1509:57borkdudeThere is one piece of support in clj-kondo for clojure.test.check: the for-all macro. Maybe we should add support for defspec too, but since it isn't there, your best bet is probably :lint-as {clojure.test.check.clojure-test/defspec clj-kondo.lint-as/def-catch-all} for now. Maybe we should add it to https://github.com/clj-kondo/configs#2022-11-1512:05skylize> How would clj-kondo know...? I am proposing that it should have built-in support.#2022-11-1512:06borkdudeissue welcome#2022-11-1512:34skylizehttps://github.com/clj-kondo/clj-kondo/issues/1882#2022-11-1512:37borkdude> The test.check library is built into Clojure itself to support this This isn't true though, test.check is not a library that comes with Clojure#2022-11-1512:37borkdudebut I still want to support this case#2022-11-1514:10skylizeBefore I wrote that, I double-checked that my tests run okay without depending on it.... but I forgot I have a user alias providing it. facepalm#2022-11-1514:13skylizeEdited it out.#2022-11-1618:12borkdudeI found a bug in clj-kondo in that it doesn't report a class name like Exception or String in a .cljc file when used in the :cljs branch and also not when used in .cljs files. Now the question is, should cases like:
(defn foo ^String [x] x)
give a warning for the CLJS context, since String isn't known in CLJS, although the compiler just ignores it
#2022-11-1618:15borkdudeIt will make writing .cljc files a bit more convenient if clj-kondo would ignore it for the CLJS side too (since the compiler doesn't complain, you will get away with less reader conditionals)#2022-11-1708:12seriogaDoes type hint for return value have any effect in cljs? I suppose that no, so ignoring is fine#2022-11-2109:24Ory BandHi. Is there a Clojure utility (or clj-kondo feature) that calculates "cognitive complexity"? there's something similiar in Rust lang that made me think https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity#2022-11-2109:41borkdudeThere is no such thing in clj-kondo#2022-11-2112:01Ory Bandany other utility that does something like this in the ecosystem? does even make sense since clojure code tends to be more "condensed" ?#2022-11-2112:02borkdudeNot familiar with such a tool myself#2022-11-2112:26tatutso it’s just cyclomatic complexity? (the past names referred to in that page suggests so)#2022-11-2114:18Ory Bandi guess? i too remember there are multiple naming for something like this. i remember in python there was a tool that checks how nested your code is i'm not even sure it makes sense in clojure due to scenarios like comp f g h and map of filter and threading etc etc#2022-11-2114:23tatutafaict composition doesn’t increase the complexity as it measures the number of different execution paths that are possible#2022-11-2114:27tatutfound some pretty ancient code https://github.com/lokori/uncomplexor/blob/master/src/leiningen/uncomplexor.clj it should be doable to make a calculation like that with clj-kondo and issue a warning if a certain threshold is exceeded#2022-11-2121:04skylizeAccording to https://ask.clojure.org/index.php/11627/the-pipe-char-considered-valid-symbol-constituent-character, and re-verified by @alexmiller moments ago in thread linked below, a pipe char | is not valid as an identifier char even though the parser will accept it. It reserved for future use at the language level. I think clj-kondo should report it as an error.
:foo|bar   ; invalid
foo|bar    ; invalid
https://clojurians.slack.com/archives/CBE668G4R/p1669064417292719?thread_ts=1669063722.432239&amp;cid=CBE668G4R
#2022-11-2212:24Benjamin
(defn foo* [{:keys [foo bar]}])
  (defn foo [{:keys [foo bar] :as opts}]
    (comment foo bar)
    (foo* opts))
am I the only one doing this so I get the eldoc for foo mentioning foo and bar The purpose of comment is to silence the kondo warning
#2022-11-2212:25borkdude@benjamin.schwerdtner you can turn linting off for unused destructured fn args: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unused-binding#2022-11-2212:26BenjaminAh interesting. I prefer the comment I think because that warning sometimes helps me#2022-11-2212:26borkdudeyou can also do:
(defn foo {:arglists '([{:keys [foo bar]}])} [m])
#2022-11-2212:26Benjaminohhh nice. This is what I was looking for#2022-11-2310:02Tuomas-Matti Soikkeliany hints why kondo reports warning from this?#2022-11-2310:04borkdudeit is unused in the sense that if you write clojure like this:
(do "foo" "bar")
the string "foo" is unused, but clj-kondo doesn't know about the fact macro, perhaps there is a config for it and it can be improved. e.g. with :config-in-call {midje.sweet/fact {:linters {:unused-value {:level :off}}}} or a more sophisticated hook
#2022-11-2310:05borkdudecc @UKFSJSM38#2022-11-2311:04ericdallointeresting corner case, but agreed, the config could go https://github.com/marick/Midje/blob/master/test-resources/clj-kondo.exports/marick/midje/config.ednfor all midje users, the same for facts , tabular I suppose#2022-11-2315:29Tuomas-Matti Soikkelithanks for the clairification, looked into config.edn and still a bit unsure how all the different macros should be configured, at least tabular gives me warnings and something like
(:require [com.rpl.specter :refer [transform ALL]])
gives me unresolved var
#2022-11-2315:30borkdudehttps://github.com/redplanetlabs/specter#clj-kondo#2022-11-2315:30Tuomas-Matti Soikkelithanks!#2022-11-2315:31borkdudewe can maybe make a clj-kondo configs library for that one (https://github.com/clj-kondo/configs)#2022-11-2315:31ericdalloOr open a PR on to make specter export clj-kondo config like midje, right?#2022-11-2315:32borkdudeNathan didn't want to include it in specter because "it would make the artifact bigger" 😂#2022-11-2315:34ericdalloreally? 😮#2022-11-2315:34ericdalloso, adding to clj-kondo/configs seems the "best" option indeed#2022-11-2315:35borkdudeat least at the time (ca. 1 year ago). we could try ask again#2022-11-2418:15seancorfieldSo I created this hook:
(ns hooks.ws.clojure.extensions.condp->
  (:require [clj-kondo.hooks-api :as api]))

(defn condp-> [{:keys [node]}]
  (let [[expr pred & tail] (rest (:children node))
        rewritten
        (api/list-node
         (list*
          (api/token-node 'cond->)
          expr
          (api/list-node (list pred expr))
          tail))]
    {:node rewritten}))
and it's in hooks/ws/clojure/extensions/condp__GT_.clj and it works -- clj-kondo correctly processes condp-> invocations everywhere -- but clj-kondo complains that the ns in that file does not match the file name (namespace-name-mismatch) which seems like a bug?
#2022-11-2418:30Noah BogartClojure can handle that natively? That’s pretty cool! #2022-11-2418:55borkdudeclj-kondo uses namespace-munge to detects if the filename corresponds to the namespace name:
user=> (namespace-munge "foo->")
"foo_>"
#2022-11-2418:56borkdudethat it works, might be accidental, since the reverse operation is probably just the general demunge#2022-11-2418:57borkdude
user=> (doc namespace-munge)
-------------------------
clojure.core/namespace-munge
([ns])
  Convert a Clojure namespace name to a legal Java package name.
#2022-11-2418:57borkdudeTo play it on the safe side, I'd just name the file condp_thread or so#2022-11-2418:58borkdudehaving > in filenames can be awkward in bash and I don't even want to know what happens in Windows :)#2022-11-2419:06seancorfieldOh, weird. namespace-munge and munge do not match?#2022-11-2419:07borkdudeno, there are some subtle differences, I can find the related clj-kondo issue for you#2022-11-2419:08borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1791#2022-11-2419:09borkdudebut if your hook worked, this is actually a bug in the clj-kondo SCI env, since it should also use namespace-munge for looking up that file :)#2022-11-2419:09borkdudehttps://github.com/clj-kondo/clj-kondo/blob/a6c31e4aa4a37c01e8aa3975ccb1c498b9761e0c/src/clj_kondo/impl/hooks.clj#L64#2022-11-2419:09borkdudeand I think I have this bug in babashka then too#2022-11-2419:48seancorfieldI guess I got the impression from earlier discussions and examples that a hook for x.y.z/abc needed to be in hooks.x.y.z.abc/abc but I gather that's not true? What are the constraints on the namespace/function name for hooks?#2022-11-2419:51borkdudeyou can make up any namespace name in the local .clj-kondo directory, as long as the namespace name corresponds to the filename.#2022-11-2419:51borkdudehooks. is just a convention#2022-11-2419:52borkdudeclj-kondo has a kind of classspath. the local .clj-kondo directory is added to that classpath, as are all two-level deep directories: acme/lib#2022-11-2419:53seancorfieldOK, so I don't need a separate file for each hook function? If a ns in my code has multiple macros that need hook definitions, I could have hooks.whatever/something.clj and that could contain all the hook fns for those macros?#2022-11-2419:53borkdudecorrect, you can stuff as many hook functions in the same file as you want#2022-11-2419:54seancorfieldCool. I can do quite a simplification of our hook setup then 🙂#2022-11-2420:39imre@U04V70XH6 would you consider adopting the .clj_kondo extension for hooks? I've come across a https://github.com/clj-kondo/clj-kondo/issues/1685 related to having hook code in .clj files.#2022-11-2420:43seancorfield@U08BJGV6E I'm talking about hooks within our monorepo at work, to handle macros in our own code, or 3rd party libraries we use that don't have clj-kondo support.#2022-11-2420:44imreoh, I misunderstood then. I was under the impression some of these were for your OSS projects#2022-11-2420:44imreapologies#2022-11-2420:44seancorfieldI'm puzzled by your issue: I don't have the .clj-kondo folder on my classpath so I can't see how an IDE would ever confuse the hook code with actual Clojure code?#2022-11-2420:45seancorfieldAnd even if .clj-kondo is on your classpath, the ns would be different and would not be something any of your code nses would ever require -- so, again, how on earth can be IDE get confused about that?#2022-11-2420:46imreIt isn't normal for .clj-kondo to be on the classpath and my issue isn't about that. The problem comes out when a library distributes its own clj-kondo hooks (among its resources), and that library is used by a consumer via a git dep.#2022-11-2420:47imrea quick repro case is
clj -Srepro -Sdeps \
 '{:deps {org.clojure/tools.namespace {:mvn/version "1.2.0"} seancorfield/next.jdbc {:git/url "" :git/sha "24bf1dbaa441d62461f980e9f880df5013f295dd"}}}' \
 -M -e "((requiring-resolve 'clojure.tools.namespace.repl/refresh-all))"
#2022-11-2420:47seancorfieldOh, you mean like this: https://github.com/seancorfield/next-jdbc/tree/develop/resources/clj-kondo.exports/com.github.seancorfield/next.jdbc/hooks/com/github/seancorfield#2022-11-2420:47imreyep#2022-11-2420:48seancorfieldHeh, yeah, well a) don't use c.t.n.r and b) don't use Cursive 🙂#2022-11-2420:48imreThere's a tools.build repro as well 🙂#2022-11-2420:48borkdudesince you prefixed that with "hooks" there is no problem#2022-11-2420:48seancorfieldWell, that's what I thought @U04V15CAJ so I'm surprised it's a problem...#2022-11-2420:49borkdudewell maybe there is, if c.t.n.r tries to load every .clj file there is on the classpath, but why would it do that, if nothing else refers to it?#2022-11-2420:50imrethat's just how c.t.n.r works, I asked about it https://ask.clojure.org/index.php/11434/could-namespace-refresh-sophisticated-directory-filtering but core aren't interested in changing that#2022-11-2420:50seancorfieldc.t.n.r is just broken (in many ways). I wish it didn't exist 😕#2022-11-2420:50imreAccording to Alex: But why are those in :paths? The whole meaning of :paths is "paths containing source to be put on the classpath". Seems like these source files should not be there if they are not source.#2022-11-2420:51imre(referring to hook code in resources)#2022-11-2420:52seancorfield@U04V15CAJ To be clear, clj-kondo will find an import foo.clj_kondo as a hook in that resources tree (as well as bar.clj)? So I could change them and it would all still work? (that extension is news to me)#2022-11-2420:52borkdude@U04V70XH6 Yes, this was implemented to solve this c.t.n.r problem#2022-11-2420:54imrehere's a https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#compatibility-with-toolsbuild-compilation in you're interested#2022-11-2420:56seancorfield@U08BJGV6E Feel free to create issues on any of my OSS projects you use that have hooks in resources and I'll make the change next time I'm working on them...#2022-11-2420:58seancorfieldnext.jdbc may be the only one?#2022-11-2421:01imreThank you Sean, will do. That's the only one among yours where I came across it#2022-11-2421:01imreAnd apologies again for hijacking the discussion#2022-11-2421:03seancorfieldI just renamed it, and it is the only hook in any of my projects as far as I can see.#2022-11-2421:06seancorfieldCurrently, the only other unreleased change in next.jdbc is a small doc example so it may be a while before I release an update for that.#2022-11-2421:08imreThanks a bunch. Since the problem only comes out when referring a lib via git coordinates, it's already fixed#2022-11-2421:09borkdude> Since the problem only comes out when referring a lib via git coordinates Why is that?#2022-11-2421:11seancorfieldYeah, that surprises me since the JAR files contains that same file/path:
655 Fri Nov 04 22:22:36 PDT 2022 clj-kondo.exports/com.github.seancorfield/next.jdbc/hooks/com/github/seancorfield/next_jdbc.clj
#2022-11-2421:17imreBecause clojure tools differentiate between namespaces coming from a directory path vs a jar path#2022-11-2421:17imreAnd git deps end up as directory paths#2022-11-2421:18borkdudeSo maybe that was the root problem that should have been fixed ;)#2022-11-2421:18imreWell at least ctnr and toolsbuild do#2022-11-2421:19imreWell, Alex's comment overrides that I think#2022-11-2421:20imreHe basically says if a .clj file isn't to be loaded it shouldn't be on the classpath#2022-11-2421:20imreAnd I wasn't successful in convincing him otherwise#2022-11-2421:20borkdudeI think compiling all namespaces, unrestricted, is usually a bad idea.#2022-11-2421:20borkdudebetter be explicit about all entrypoints (which is usually just one)#2022-11-2421:22borkdudeI've had problems with this in both lein and tools.build with duplicate compiled namespaces + graalvm native-image and since then I always use an explicit list#2022-11-2421:22seancorfielddeps-new has a bunch of .clj files in resources because they are templates for generating new projects -- but they are mostly illegal Clojure code and the ns in particular is not a valid symbol... but almost no one would have deps-new on their classpath while working on other stuff 🙂#2022-11-2421:23seancorfield(`clj-new`, boot-new, and lein new code all do the same -- and those .clj files are in the codebase, not even just restricted to resources)#2022-11-2421:24imreI'm with you, I tried to phrase something like this at https://ask.clojure.org/index.php/11434/could-namespace-refresh-sophisticated-directory-filtering?show=11880#c11880#2022-11-2421:25imreAlex responded to it#2022-11-2421:33imreAnd his suggestion was to use a different extension#2022-11-2421:34imreWhich is why I created the kondo issue in the end#2022-11-2421:37seancorfieldI'm reminded of https://corfield.org/blog/2018/04/18/all-the-paths/ wherein I examine how different tools deal with different "types" of paths -- and Leiningen in particular had :source-paths and :resource-paths (Boot also had these two keys but they meant different things of course).#2022-11-2421:41borkdudehaha yes, I could never figure out what boot meant with which key#2022-11-2421:41seancorfieldhttps://github.com/seancorfield/deps-new/issues/39 -- for "completeness" on this topic 🙂#2022-11-2421:53imreNice article, Sean. In the end it all comes down to what is on the classpath at runtime.#2022-11-2420:30dharriganDo you think it might be worthwhile for the clj-kondo --lint src command to output just the filenames (if it finds warnings/errors) for loading up into an editor? For example, something like vim $(clj-kondo --lint src --raw), then when it's loaded into an editor (in my case, vim with clojure-lsp), those errors would flag up when the analysis has been done?#2022-11-2420:31borkdude@dharrigan the format that is currently spit out is already made in a standard way that editors recognize#2022-11-2420:32dharriganerrr, not really#2022-11-2420:32dharrigandoing "vim clj-kondo --lint src"
#2022-11-2420:32dharriganshows me over 24 files to edit....#2022-11-2420:33dharriganvim certainly can't parse output like linting took 158ms, errors: 0, warnings: 4#2022-11-2420:42Noah BogartUsing :cfile, you can just load a file with kondo’s normal output#2022-11-2420:34borkdudewhat I mean is that when you open this format in an editor, it usually knows what to do with it. https://github.com/borkdude/carve#report-mode#2022-11-2420:35dharriganThat report mode would not be recognised by vim#2022-11-2420:37dharriganJust tried it with vim and well, no.#2022-11-2420:38borkdude@dharrigan clj-kondo --lint src --config '{:output {:pattern "{{filename}}"}}'#2022-11-2420:39dharriganThat would still fail for me#2022-11-2420:39dharrigansince it outputs#2022-11-2420:39dharriganlinting took 157ms, errors: 0, warnings: 4#2022-11-2420:40borkdude
clj-kondo --lint src --config '{:output {:pattern "{{filename}}" :summary false}}'
#2022-11-2420:41dharriganThat works for sure, but mamma mia, so much typing...#2022-11-2420:41dharriganI suppose I could alias it#2022-11-2420:41borkdudedude, I'm giving you a solution, when are you finally satisfied? ;)#2022-11-2420:43dharriganMy apologies.#2022-11-2420:43borkdudeI guess we could print the summary to stderr instead of stdout#2022-11-2420:44borkdudebut since we have a config option and it might break existing tools somehow, maybe not necessary#2022-11-2420:44borkdudeyou can put this command in a bb.edn tasks file or makefile or a bash alias#2022-11-2420:50borkdude@dharrigan sorry I sounded a little agitated#2022-11-2421:08borkdude@dharrigan I guess what I meant earlier is that when you command click in your terminal, and you have the right default editor set, the file will open at the right location with the current output. This works at least for me + VSCode (for some reason that editor is set for my terminal right now), but of course your terminal has to support this too#2022-11-2421:13borkdudeHere's what I'm seeing:#2022-11-2514:29pezShould the unused public var linter flag when a var is referenced quoted?
(def foo :foo)
(def foo-q 'foo)
foo is flagged as unused. Maybe it should, come to think of it...
#2022-11-2514:31borkdude@pez quoted symbols naming vars do not count as var references, currently. but we talked recently about this, that it might be interesting for clojure-lsp to do regard it as a reference for navigation purposes#2022-11-2514:32borkdudeIt does count when you write foo` since syntax quote will use the environment to resolve the var so in that sense the var is "used"#2022-11-2514:56pezTIL!#2022-11-2523:58Søren SjørupI have a ns with many unused public vars, as I bind them dynamically. How do I ignore the :clojure-lsp/unused-public-var warning for the entire ns? #_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]} in front of each def works as expected.#2022-11-2607:10borkdudeSee Clojure-LSP config docs #2022-11-2608:20borkdudehttps://clojure-lsp.io/settings/#clojure-lspunused-public-var#2022-11-2715:33Søren SjørupAh that did it, thank you! I was setting :level :off didn’t realize I could just exclude the linter as such.#2022-11-2812:44Tim JanssenWhat options can be passed to run! in the clj-kondo babashka pod? Is there a way to run the equivalent of: clj-kondo --lint "$(clojure -Spath)" --dependencies --parallel --copy-configs using the pod?#2022-11-2812:45borkdude
{:lint [(:out (babashka.process/shell {:out :string} "clojure -Spath"))]
 :dependencies true
 :parallel true
 :copy-configs true} 
#2022-11-2812:50borkdudeYou can view the API here: https://github.com/clj-kondo/clj-kondo/blob/master/API.md#clj-kondo.core/run!#2022-11-2812:50borkdude^ @tim867#2022-11-2812:53Tim JanssenPerfect! Thanks @borkdude!#2022-11-2912:29practicalli-johnFYI I've created a PR to update Megalinter to 2022.11.02 version of clj-kondo and update a config the automated bot has missed. https://github.com/oxsecurity/megalinter/pull/2114#2022-11-2912:31practicalli-johnNormally an automated bot updates the version of clj-kondo, but one of the checks has failed. Hopefully the bot is fixed or the above PR is applied (or both)#2022-11-2918:24d._.bHello, by default clj-kondo (clojure-lsp) drops configuration for metosin and clj-rewrite into my .clj-kondo/ dir. What is the reason for this?#2022-11-2920:41ericdalloclojure-lsp passes a flag for kondo to copy those configs, for clj-kondo lint macros properly#2022-11-2920:41borkdudeyes @U20LDTZBJ - so the reason is that you're using dependencies that have those configs, which makes linting work correctly out of the box when you use those libs#2022-11-2921:21d._.bthanks!#2022-12-0116:23sheluchinHey @borkdude, I've been looking for ways to relate clj-kondo usage analysis data to source libraries rather than just source namespaces. I've kind of asked about this in a few different places, but ultimately it seems to come down to operating on :lib values. Do you have any thoughts on the feasibility of including :lib keys in the analysis output? https://clojure.org/reference/deps_and_cli#find-versions#2022-12-0116:30borkdudeI once made a library which may help a bit with this problem: https://github.com/borkdude/deps-infer#2022-12-0116:31borkdudeclj-kondo doesn't analyze deps.edn, project.clj or pom.xml, it just inspects .jar files and .clj files, so it has no idea which lib and version this is, but combined with the above you may be able to solve that problem#2022-12-0117:32sheluchinAnother piece to the puzzle! I will check out deps-infer in detail. What about inspecting the pom.xml in the jar files, is that something you would consider, or it's out of scope for clj-kondo? > Download an index of all of Clojars for inferencing of deps that are not in your local .m2/repository. This index must be kept up to date, e.g. daily, and be committed to some git repo where we can then fetch it. I need to look closer, but maybe https://github.com/phronmophobic/dewey can be used for this.#2022-12-0117:33borkdudeI would say it's out of scope / work that can be done in another tool, at least for now#2022-12-0117:34sheluchinThank you.#2022-12-0117:37borkdudeunless it can be done in very pure way that doesn't add a lot of deps, etc. perhaps you can figure this out and if it's small enough, it could live in clj-kondo eventually#2022-12-0212:11sheluchinPart of the problem I'm trying to solve is to be able to link namespaces to libs without downloading the libs. I'm not entirely sure this is even possible. Do you know? In the case of deps-infer, it works by scanning your .m2/repository, which obviously depends on libs being downloaded. The way I get around it now is by first downloading a given lib, running analysis on it to store all of its definitions, and then downloading one or more of repos that use the lib, and matching their usages' :to to the definitions of the lib. It's not a perfect process, but works well enough. I would just like it to work better 🙂#2022-12-0212:17borkdudewhen you're analyzing a lib, isn't the lib already there?#2022-12-0212:21sheluchinYes lol it is. What I would like is to be able to look at any given repo and understand how its namespace usages map to the libs listed in one of its project files (deps.edn, project.clj, etc.). I'm looking to kind of invert the process I'm currently using, and not depend so much on analyzing repos in the context of a specific lib.#2022-12-0212:23borkdudewell, you can do this using deps-infer. start with a clean m2 directory (or set an alternative m2 directory). download deps. analyzes sources. run deps-infer and have the answer, kind of#2022-12-0213:08sheluchinBut that's back to downloading the libs, which is the thing I'm trying to avoid (which might be unavoidable). Unless I'm misunderstanding..#2022-12-0213:09borkdudeI don't understand, since you need the deps to analyze them in the first place#2022-12-0213:10sheluchinIs it possible to infer what dep a required namespace points at without creating a runtime or running analysis on the full set of deps?#2022-12-0213:11borkdudenot without a global lookup table of all the deps in the entire universe that has once been populated#2022-12-0213:11borkdudealso note that deps can make up any namespace they want, so namespaces might not be globally unique#2022-12-0213:15sheluchinI wish this were otherwise 🙂 like if required namespaces were transparent about their source dep... but okay, it sounds like I'd be better off starting off with creating that global namespace lookup table and then dealing with conflicts separately when trying to figure out where usages come from.#2022-12-0213:17borkdudeI once had a conversation in clojars, to populate such a global lookup table from all deps in clojars#2022-12-0213:17borkdudeby running deps-infer#2022-12-0213:17borkdudeyou might able to find it in #C0H28NMAS and re-spawn that discussion#2022-12-0213:50sheluchinI guess you mean this https://clojurians.slack.com/archives/C0H28NMAS/p1614172498008700#2022-12-0213:53borkdudeah indeed#2022-12-0213:54sheluchinThanks for the feedback and pointers. I'm still not totally sure about the best strategy for me at the moment, but the mess in my mind will make sense after bit of time.#2022-12-0213:55borkdudehammock time :)#2022-12-0213:55sheluchinIn case anyone comes across this thread looking for something related, I also found https://github.com/rads/deps-info, which is kinda related, but so far I haven't managed to squeeze much juice out of it.#2022-12-0213:57borkdudea funny detail is that he called this library deps-infer too, but then I told him that I already had a library called like that ;)#2022-12-0213:59sheluchinI don't know how you manage to do so much. There would probably be some interest if you were to share a little of your thought process and philosophy of development... although, you've probably already done that too 😛#2022-12-0214:05borkdudejust one step at a time :)#2022-12-0222:15Joshua Suskaloheads up, it looks like defining a function with the name * gets warned as being a non-dynamic earmuffed var#2022-12-0222:16Joshua SuskaloI'd personally argue any var with a name matching \*+ probably isn't earmuffed#2022-12-0222:19borkdude@suskeyhose Thanks. Issue with false positives welcome#2022-12-0222:24Joshua SuskaloAh, interesting. Only happens on multimethods. I'll put it in the issue.#2022-12-0222:26Joshua Suskalohttps://github.com/clj-kondo/clj-kondo/issues/1896#2022-12-0222:27borkdudeI hope to do a new release next week Wednesday or so. For now you can use #_:clj-kondo/ignore .#2022-12-0222:27Joshua Suskalosounds good#2022-12-0519:34orestis
(when-let [x ""]
  x
  "foo")
The unused-value warning is helpful but it seems it fails to catch some common use cases (in my case, I should have put an if-let - I'm relying on clj-kondo very much these days it seems 🙂
#2022-12-0519:35borkdudeissue welcome to improve this case#2022-12-0519:42orestis👍#2022-12-0519:51orestishttps://github.com/clj-kondo/clj-kondo/issues/1899 Thanks!#2022-12-0610:06Jakub Holý (HolyJak)Hi! Where does the “Unused alias” lint error come from? Searching the codebase and linters.md yields nothing. I would like to learn how to tell Kondo to ignore it in this case… 🙏#2022-12-0610:08borkdude@U0522TWDA I've never seen this message coming from kondo, but I could be wrong. You can enable this to see the linter name: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#show-linter-name-in-message Could you please provide a repro?#2022-12-0610:12Jakub Holý (HolyJak)I see, sorry, it comes from Cursive itself 😅#2022-12-0710:09Ben SlessShould an arg hinted as ^double be an error when it's provided as a long? Clojure's compiler just casts it#2022-12-0710:18borkdudeHow does this question relate to clj-kondo and can you give a code snippet / repro to explain what you're talking about?#2022-12-0710:21borkdudeDo you mean this?
$ clj-kondo --lint - <<< '(defn foo [^double x] x) (foo 1)'
<stdin>:1:31: error: Expected: double, received: positive integer.
#2022-12-0710:25Ben SlessExactly#2022-12-0710:26Ben SlessThat's a kondo related question, no?#2022-12-0710:26borkdudeyes, but it wasn't clear to me when you first posted your message#2022-12-0710:26borkdudeyes, I think this should be fixed#2022-12-0710:27borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1903#2022-12-0711:45Ben SlessThanks!#2022-12-0716:20Benjaminpromesa has a clj kondo exports file defined? What do I need to do to reap this when using nbb?#2022-12-0716:22borkdudeGood question. You can add it to deps.edn or bb.edn and then clojure-lsp will do it for you. Using clj-kondo alone: • Create a .clj-kondo directory • Run clj-kondo --copy-configs --lint "$(clojure -Spath)" --dependencies#2022-12-0716:23BenjaminI see#2022-12-0716:23Benjaminthanks#2022-12-0716:29Benjaminif clojure -Spath could be made aware of nbb's builtin deps that would be ultimate smoothness#2022-12-0716:32borkdudeagreed#2022-12-0716:32borkdudewe've done this for babashka, it may happen at some point for nbb too#2022-12-0716:32Benjaminoh#2022-12-0716:32borkdudelsp recognizes bb.edn and then it inserts some configs for built-in deps for bb#2022-12-0716:33Benjaminmaybe this could also be configured via .clojure say deps resolvers functions#2022-12-0716:33borkdude?#2022-12-0716:35Benjaminwell whatever. I was just wondering if it could be in user space.#2022-12-0716:35borkdudeyou can do it in user space via lsp config#2022-12-0716:35borkdudebut it requires some configuration#2022-12-0716:35borkdudeyou can tell lsp what classpath to use for analysis and you can use a bb or nbb script for this#2022-12-0716:38BenjaminI tried adding
:deps {funcool/promesa {:mvn/version "10.0.571"}}
to bb.edn and now it put spec.alpha and clojure-1.11.1 in the classpath but not prromesa. I was expecting this differently
#2022-12-0716:38Benjamin
clojure -Spath 
src:/home/benj/.m2/repository/org/clojure/clojure/1.11.1/clojure-1.11.1.jar:/home/benj/.m2/repository/org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar:/home/benj/.m2/repository/org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar
#2022-12-0716:39BenjaminI thought I can copy the exported config now 😛#2022-12-0716:39borkdudewhat I mean with bb.edn is: just put it there and then restart clojure-lsp#2022-12-0716:39borkdudeclojure -Spath doesn't look at bb.edn#2022-12-0716:39Benjaminah#2022-12-0716:39Benjaminah yea it pulled those because I added an empty deps.edn and forgot it#2022-12-0716:40Benjaminah so only lsp does some magic, not the level of kondo?#2022-12-0716:40BenjaminI guess I need to pass --copy-configs#2022-12-0716:40borkdudewith kondo only, use the second option I posted in first reply#2022-12-0716:41borkdudemore details here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2022-12-0716:42Benjaminahh 👍#2022-12-0716:22borkdudeGood question. You can add it to deps.edn or bb.edn and then clojure-lsp will do it for you. Using clj-kondo alone: • Create a .clj-kondo directory • Run clj-kondo --copy-configs --lint "$(clojure -Spath)" --dependencies#2022-12-0722:49snoeI believe there's either a change or bug in hook handling that is messing up lsp. If a hook introduces a token like letthe name-* meta is getting filled in for strange blocks of the form. 🧵#2022-12-0722:53snoeHere, using the with-bound hook from the example doc, we can see that the w in what highlights the entire form. This is because the name-row/end-row goes from 4-6 and name-col/end-col is 1-7. If we ask what is under the cursor, we see it's picking up the let#2022-12-0722:54borkdudeThere has been a change where things from hook that don't have locations get a :derived-location so you can still see where it's from more or less. It could be that clojure-lsp doesn't always take this into account. cc @UKFSJSM38#2022-12-0722:55snoeThe derived-name-location isn't right though, a name can't span rows#2022-12-0722:57borkdudethe reason here is that the location is derived from the surrounding form that does have a location. derived locations aren't accurate and can be ignored if they lead to issues#2022-12-0722:58borkdudeI'll be afk now, but if you have more to share on this or want to do a deeper diagnosis: I will release a new version of clj-kondo tomorrow so the more time you can save me by doing some pre-work on this, the better#2022-12-0722:58borkdude💤#2022-12-0723:03ericdallo@U0BUV7XSA this probably points that your hook should have a with-meta otherwise that will happen#2022-12-0723:04ericdallohttps://github.com/nubank/state-flow/blob/master/resources/clj-kondo.exports/nubank/state-flow/nubank/state_flow.clj#L34#2022-12-0723:07snoeI think there's two issues: 1. The name-* metadata when derived-name-location is true should derive from the name, not from the form. 2. There's no way afaik, for a hook to say that a derived token should be included in analysis output or not, also the derived-name-location flag is insufficient for lsp to know which should be ignored or kept. a. Some macros can combine names like (defendpoint a "b" ...) => (defn a_b ...) a_b should be derived otherwise really nasty metadata calculation has to be done by hook authors. b. In the example above, the let probably shouldn't leak into analysis at all, since it's not actually present in the form, nor should it be considered a var-usage of clojure.core/let#2022-12-0723:08snoe@UKFSJSM38 but there's no valid position for that let in the example.#2022-12-0723:11snoe@UKFSJSM38 I think that before derive-* was introduced the locations would be nil maybe in lsp we could change them back to nil as that would at least cause far fewer issues than what I'm now seeing with library hooks that do not specify meta#2022-12-0723:13ericdalloTBH not sure, that was a headache on Nubank's state-flow and derived-name-location kind of fixed that regression, I think we added tests for that but would need to do carefully#2022-12-0723:14ericdalloYour macro is pretty similar to nubank/state-flow defflow macro regarding the let, maybe you could try adding the with-meta and check if still have the issue#2022-12-0723:16snoeThat's just the macro in the kondo docs. The macros at metabase are much more complicated and I did start adding meta but it's starting to hit a wall because of 2b above.#2022-12-0723:18ericdalloso you are suggesting to make name locations nil when they are derived instead of ignoring totally those analysis?#2022-12-0723:23snoeI think 1. kondo should fix derived names to be based on name not form as they are giving impossible dimensions for names. 2. kondo introduces an api/internal-node function or something that would hide (or mark) nodes that are not reflected in the code from being output to analysis. Until then, lsp should probably make name locations nil when derived.#2022-12-0723:24snoeWe'd have to see what that does to rename though#2022-12-0723:25ericdalloI like 1, let's see what borkdude think about that, meanwhile we could test it namking name locations nil, I'd like to do that carefully if possible (not include on tomorrow's release)#2022-12-0723:31snoeHere's a macro that is registering a usage of my dosomething fn, then what happens if I rename it.#2022-12-0723:32ericdalloyeah, pretty undesired behavior#2022-12-0723:33snoeAnd I don't think there's a meta position i can apply that wouldn't mess things up#2022-12-0723:34ericdalloyeah, me too, we could ignore specific analysis on rename, but sounds like a weird workaround... probably ignoring or fixing it on kondo side or lsp parsing kondo analysis is the best#2022-12-0811:56borkdudeIf you have a proposal, let me know#2022-12-0811:58borkdudethe approach with derived locations is "something is better than nothing". e.g. if you have a lint warning about the name, but there is no location, it will appear at the location of the surrounding form#2022-12-0811:58borkdudeif there is no location to point to, the lint warning would not appear anywhere#2022-12-0815:43borkdudeNew release!#2022-12-0905:42robert-stuttaford@borkdude please may we have the new clj-kondo in bb pod form? 😄
----- Error --------------------------------------------------------------------
Type:     java.io.FileNotFoundException
Message:  
#2022-12-0909:13borkdudeI'll do this in an hour, sorry... again :)#2022-12-0909:24robert-stuttafordhaha its ok!#2022-12-0910:04borkdudedone!#2022-12-0911:58robert-stuttafordthank you!#2022-12-0909:40Pratik
clj-kondo: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by clj-kondo)
30clj-kondo: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by clj-kondo)
we are getting this error in our CI pipeline stage that runs clj-kondo, could it be due to latest clj-kondo version? moving to previous version(2022.11.02) fixes it
#2022-12-0910:01lispycloudsIs this the static binary? And which OS is this?#2022-12-0910:02PratikIt runs under ubuntu 20.04 image#2022-12-0910:04lispycloudsright and how is the clj-kondo binary downloaded? is it an script install or something else?#2022-12-0910:04Pratikyep, I think we run this
bash <(curl -s )
#2022-12-0910:06borkdudeI'm also getting this in a docker ubuntu image :/ /cdn-cgi/l/email-protection:/# clj-kondo qemu-x86_64: Could not open '/lib64/ld-linux-x86-64.so.2': No such file or directory#2022-12-0910:08lispycloudswhat does ldd <clj-kondo-binary> and file <clj-kondo-binary> say?#2022-12-0910:09lispycloudshas graalvm increased base glibc version?#2022-12-0910:09borkdudeit does work for me when I do:
docker run --rm --platform linux/x86_64  -it ubuntu
#2022-12-0910:09borkdude@U01PG2LDYV8 Could it be you're running in docker as well?#2022-12-0910:10lispycloudsyeah the above error you got is an arch mismatch @borkdude#2022-12-0910:11Pratikyes, running it in docker#2022-12-0910:12borkdudeon wsl2 I also get:
$ /home/borkdude/.linuxbrew/bin/clj-kondo
/home/borkdude/.linuxbrew/bin/clj-kondo: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /home/borkdude/.linuxbrew/bin/clj-kondo)
/home/borkdude/.linuxbrew/bin/clj-kondo: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /home/borkdude/.linuxbrew/bin/clj-kondo)
#2022-12-0910:13lispycloudscould you tell what ldd clj-kondo says? not at a linux machine atm#2022-12-0910:14borkdude
$ ldd /home/borkdude/.linuxbrew/bin/clj-kondo
/home/borkdude/.linuxbrew/bin/clj-kondo: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /home/borkdude/.linuxbrew/bin/clj-kondo)
/home/borkdude/.linuxbrew/bin/clj-kondo: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /home/borkdude/.linuxbrew/bin/clj-kondo)
        linux-vdso.so.1 (0x00007ffc60758000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f0a76c5a000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0a76a68000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0a796e9000)
#2022-12-0910:15lispycloudsand ldd --version ?#2022-12-0910:15lispycloudsthere should be a glibc somewhere there#2022-12-0910:15borkdude
$ ldd --version
ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31
#2022-12-0910:16lispycloudswell something has increased the base requirement, my suspicison is native-image#2022-12-0910:16lispycloudsnewer linux images might work. ubuntu 22 i think#2022-12-0910:16borkdudeI haven't heard about this problem with babashka#2022-12-0910:17borkdudebb works just fine#2022-12-0910:17borkdudecould it be related to the alpine thing I "fixed" yesterday?#2022-12-0910:18lispycloudswell thats only on the alpine image#2022-12-0910:20borkdudeyeah, so this was the only change in the circleci build: https://github.com/clj-kondo/clj-kondo/commit/a3c9282e2160ec227c46d8dd71d43c49b4fb9aae#2022-12-0910:21borkdudeI'm using the same graal version for bb#2022-12-0910:22lispycloudsbut this seems to be graal 17 and bb is 11 i guess?#2022-12-0910:22borkdudegraal 17...?#2022-12-0910:22lispycloudsGRAALVM_HOME: /home/circleci/graalvm-ce-java17-22.3.0 java17#2022-12-0910:22borkdudeoh, I didn't even realize that#2022-12-0910:23lispycloudsalso i see a mix of 11 and 17 in the circle yaml#2022-12-0910:24borkdudeyeah I never intended to upgrade to 17#2022-12-0910:24borkdudefuck#2022-12-0910:24borkdudebut this should work as well, right#2022-12-0910:24borkdudeso I'll ask in the graalvm chat#2022-12-0910:25lispycloudsi think so, im just going on the hunch of something bumping the glibc version. reading the release notes#2022-12-0910:25lispycloudswe could try setting it all to java11 as bb?#2022-12-0910:26borkdudeI see:
GraalVM will no longer run on some older Linux AMD64 distributions. It is now built against glibc 2.17 (instead of 2.12), and as a result it may not run on Oracle Linux 6 or other RHEL 6 derivatives.
#2022-12-0910:27borkdudein https://www.graalvm.org/release-notes/22_2/#2022-12-0910:27lispycloudswell this is still older than whats here#2022-12-0910:29borkdudeyeah#2022-12-0910:29borkdudeI started a discussion here: https://graalvm.slack.com/archives/CN9KSFB40/p1670581560658649#2022-12-0910:44borkdudeNow I also get why the github action broke#2022-12-0910:45borkdudehttps://github.com/clj-kondo/clj-kondo/actions/runs/3649794985/jobs/6164932624#2022-12-0910:45borkdudeeven though it's not clear from the error message, I'm almost certain it has to do with this#2022-12-0910:51borkdudenope java11 didn't help either https://app.circleci.com/pipelines/github/clj-kondo/clj-kondo/5107/workflows/156f979b-bed1-479d-b28f-dafee5d9e054/jobs/21245/steps#2022-12-0910:53borkdudeperhaps if it detects a too new glibc version on the CI host machine it links against that?#2022-12-0910:54lispycloudsyeah im thinking that too. could you try ldd --version on cimg/clojure:1.11.1-openjdk-17.0#2022-12-0910:54borkdudeI'm doing this in ssh in circleci now:
$ ldd --version
ldd (Ubuntu GLIBC 2.35-0ubuntu3.1) 2.35
#2022-12-0910:56lispycloudsi believe the linux amd64 is in docker? https://github.com/clj-kondo/clj-kondo/blob/master/.circleci/config.yml#L56#2022-12-0910:56borkdudeOn the machine:
$ ldd ./clj-kondo
	linux-vdso.so.1 (0x00007ffcac1d4000)
	libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1bc2f19000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f1bc2efd000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1bc2cd5000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1bc2bee000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f1bc5ba9000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1bc2bce000)
#2022-12-0910:57lispycloudsyeah but the error is about 2.32 and 2.34#2022-12-0910:57borkdudemakes no sense to me#2022-12-0910:58lispycloudscould try a shell in a container of cimg/clojure:1.11.1-openjdk-17.0 and see the ldd version there?#2022-12-0910:58borkdudesure#2022-12-0910:58lispycloudsthats where its built in ci#2022-12-0910:58borkdudewhen I ssh into the machine, am I not logging into the running docker img then?#2022-12-0910:59lispycloudsno, its the raw instance#2022-12-0910:59borkdudeconfusing#2022-12-0911:00borkdude
$ ldd --version
ldd (Ubuntu GLIBC 2.35-0ubuntu3.1) 2.35
#2022-12-0911:00borkdudelooks exactly like the output above (so I think I'm in the same docker img, really)#2022-12-0911:01lispycloudsyeah also the lower kernel is shared so doesnt matter much#2022-12-0911:01borkdudeOh, here's a difference, you're right:
$ uname -a
Linux 3320512d8efc 5.15.0-1021-aws #25~20.04.1-Ubuntu SMP Thu Sep 22 13:59:08 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
$ uname -a
Linux b3097fb367af 5.10.76-linuxkit #1 SMP PREEMPT Mon Nov 8 11:22:26 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
#2022-12-0911:02lispycloudsah, could be the container being scheduled on different machines?#2022-12-0911:02borkdudeanyway, let's focus on the libc thing#2022-12-0911:02borkdudeI can try to downgrade to the older stuff that bb uses#2022-12-0911:03borkdudeor just drop the dynamic binary and do static everywhere#2022-12-0911:03borkdudeexcept that isn't possible on aarch64#2022-12-0911:03lispycloudsfully static should be better in kondo's case than bb#2022-12-0911:04borkdudewhy so? > + > except that isn't possible on aarch64#2022-12-0911:05lispycloudsyeah the aarch64 issue aside, iirc we do a mostly static build in bb due some issues right?#2022-12-0911:06lispycloudsnot fully static#2022-12-0911:08lispycloudshttps://github.com/oracle/graal/issues/3737#2022-12-0911:08borkdudethe issue is just that musl doesn't work for aarch64#2022-12-0911:09lispycloudsright, i guess we are talking about the same thing then#2022-12-0911:13borkdudeI'll port the install script to download the static binary on linux...#2022-12-0911:17lispycloudsreally trying to diff bb's and kondo's build, bb using circleci/clojure:openjdk-11-lein-2.9.8-bullseye vs cimg/clojure:1.11.1-openjdk-17.0 in kondo for docker builds and machines elsewhere. my thoughts are things couldve updated in the cimg base images and the binary links there#2022-12-0911:18lispycloudsthe circleci/... images are deprecated and possibly never got updated#2022-12-0911:19lispycloudsi can try to have a deeper look on better machines a bit later in the day. downloading the static one should be a stop gap thing for now i think too#2022-12-0911:25borkdudeI know they're deprecated#2022-12-0911:25borkdude@U01PG2LDYV8 Could you try the install script again? I now tweaked it so it uses the static binary always on linux#2022-12-0911:26borkdudeAt least it works for me now in wsl2#2022-12-0911:26lispyclouds> I know they're deprecated yeah thats one thought in my head how things could break#2022-12-0911:26borkdudewell, it still works with the deprecated images ;)#2022-12-0911:26borkdudeI didn't upgrade to cimg myself on clj-kondo, it was a PR#2022-12-0911:27Pratikit’s working!#2022-12-0911:28borkdudeI'll deprecate the non-static image in clj-kondo and babashka on linux in the future except on aarch64, saves maintaining another build too#2022-12-0911:28lispycloudssounds good to me#2022-12-0911:30kokadaLGTM#2022-12-0911:31kokada> I'll deprecate the non-static image in clj-kondo and babashka on linux in the future except on aarch64, saves maintaining another build too Any news about static builds in aarch64-linux?#2022-12-0911:31borkdudestill same: mostly static except libc#2022-12-0911:33kokadaBTW, not related#2022-12-0911:33kokadaProbably will try to bump zlib to 1.2.13#2022-12-0911:34kokadaThere are a few CVEs related to 1.2.11 and 1.2.12, and I think they fixed the issue that caused the errors in 1.2.12#2022-12-0911:34lispycloudsI can have a look at it if you send a PR @UFDRD93RR#2022-12-0911:34kokadaSure#2022-12-0911:35kokada
Correct incorrect inputs provided to the CRC functions. This mitigates a bug in Java. 
Yeah, looks like they fixed the issue specially for Java lol
#2022-12-0911:37borkdudegeez, it really helps to have mac + amd / aarch64 + windows + linux at home for these kinds of things.. I made a mistake on macos + static in the bash script which I could test on my older macbook which is still amd64#2022-12-0911:37lispycloudsso much for Java's Write Once, Run Anywhere#2022-12-0911:38kokadaWrite Once, Debug Anywhere more likely#2022-12-0911:38borkdudethat's the issue with distributing binaries#2022-12-0911:38borkdudenot java's problem, native image problem#2022-12-0911:38lispycloudsyeah was sarcasm 😛#2022-12-0911:38kokadaJava does have a few issues with multi-platform though 😛#2022-12-0911:39kokadaI am trying to get openjdk inside nixpkgs up-to-date and it is a mess#2022-12-0911:39borkdudeSee "Targeting multiple platforms" paragraph here: https://medium.com/graalvm/babashka-how-graalvm-helped-create-a-fast-starting-scripting-environment-for-clojure-b0fcc38b0746#2022-12-0911:40borkdudeI'll also update the brew formula to pick the static binary from now on#2022-12-0911:40lispyclouds< Insert rewrite in Rust joke here >#2022-12-0911:44borkdudebrew formula also updated, works on my ubuntu now#2022-12-0911:45borkdudethe issue with the musl binaries was that their stack size is tiny except when you run them in a thread (which is then configurable) which caused issues for bb#2022-12-0911:45borkdudeso when in musl, the whole main program is running inside a "dummy" thread#2022-12-0911:46borkdudethe overhead for that is probably small enough to not worry about it#2022-12-0911:50borkdudeGoing with this in the bb install script as well:
*) arch=amd64
       # always use static image on linux
       if [[ "$platform" == "linux" ]]; then
           static_binary="true"
       fi
       ;;
#2022-12-0911:50borkdudeI hope that will prevent questions / confusions like these: https://github.com/babashka/babashka/issues/1434#2022-12-0911:53borkdudedone:
$  bash <(curl -s ) --dir /tmp
Downloading  to /tmp/tmp.yP24TUxaOO
Moving /tmp/bb to /tmp/bb.old
Successfully installed bb in /tmp
#2022-12-0911:58borkdudeBrew bb formula also updated#2022-12-0911:59borkdudeI wonder if running the whole main program in a thread means bb could use less cores...#2022-12-0911:59borkdudeprobably not right#2022-12-0912:06kokada> I wonder if running the whole main program in a thread means bb could use less cores... It will use extra stack and there is a small overhead. Not really measurable, specially on Linux that is really efficient with Threads#2022-12-0912:06kokadaIf this was in macOS or Windows (in WSL1 specially), you probably can measure some difference#2022-12-0912:08borkdudecool#2022-12-0912:09kokadaIt seems the Dockerfile has a few issues...#2022-12-0912:10kokada
GraalVM only supports building static binaries on x86_64.
#2022-12-0912:11borkdudethis is "our" message ;)#2022-12-0912:11kokadaYeah I know#2022-12-0912:12kokadaWe basically set BABASHKA_ARCH to amd64 somewhere in the process#2022-12-0912:12kokadaThat is clearly wrong#2022-12-0912:24kokada@U7ERLH6JX https://github.com/babashka/babashka/pull/1445#2022-12-0912:24kokadaCC @borkdude#2022-12-0912:25borkdude@UFDRD93RR can you explain why those defaults are removed? it's been a while ... :) cc @U7ERLH6JX#2022-12-0912:26kokadaWith the defaults I was having the issue above#2022-12-0912:26kokadaThey're also clearly wrong#2022-12-0912:26kokadaBecause TARGETARCH for amd64 should not set BABASHKA_ARCH to amd64 too#2022-12-0912:27kokada(`BABASHKA_ARCH` should be x86_64)#2022-12-0912:29lispycloudsJust fyi, I’ll try to have a look in a bit later today. Reaching to better machines and time hopefully 😅 #2022-12-0912:32borkdudeok @U7ERLH6JX I'll let you review + merge this when you have time#2022-12-0913:49borkdudeThe advice from graalvm slack: build with the oldest ubuntu possible#2022-12-1008:58borkdudeDamn, even Ubuntu 22 can't run that image: https://github.com/clj-kondo/clj-kondo/issues/1909#2022-12-1009:21borkdudeI'm doing another clj-kondo release with a docker image that uses the SHA of the image that was used in the previous version#2022-12-1009:34lispycloudsGreat that you found the SHA! I'm semi glad too that glibc getting bumped externally hunch played out and we now know where too.#2022-12-1009:37lispycloudsi looked at glibc version on ubuntu:22.04 docker now, its at 2.35. when they move everyone else is moved too i guess#2022-12-1009:51borkdudebut how quickly :)#2022-12-1009:59borkdudeAaand the Github action started working again too https://github.com/clj-kondo/clj-kondo/actions/runs/3663694967/jobs/6193635075#2022-12-1010:01lispycloudswell, annoying but useful learnings. at least for me 😛#2022-12-1010:01borkdudeI've had this problem before I think once#2022-12-1010:02borkdudeIn graal we had a discussion on being able to set a lower glibc version in the native image despite the build env#2022-12-1010:02borkdudehope they will support that, but I guess you'd also have to deal with zlib etc#2022-12-1010:03lispycloudsat least zlib isnt fine grained into the OS like glibc. can control it better#2022-12-1010:03borkduderight
#2022-12-1010:03borkdudeI guess glibc is the most difficult one#2022-12-1010:04lispycloudswell if youre google and you solve it by inventing a whole glibc free language to get around it 😅#2022-12-1010:06lispyclouds> on being able to set a lower glibc version in the native image despite the build env thats some complex bin stubs and magic there i think#2022-12-1010:09borkdudeit's just a constant in the binary#2022-12-1010:09borkduderemember that nixos tools can override this too using some tool which rewrites that constant in some table#2022-12-1010:09lispycloudsah right#2022-12-1010:01borkdude#2022-12-1119:08lilactowncan I configure clj-kondo to ignore all warnings inside of a specific macro?#2022-12-1119:09lilactowne.g.
(my-special-macro foo bar baz)
I just want clj-kondo to ignore all forms inside my-special-macro for now
#2022-12-1119:09borkdude@U4YGF4NGM not all warnings, but you can tweak specific linters within a macro#2022-12-1119:09borkdudeTry:
{:config-in-call {your/macro {:linters {:unresolved-symbol ...}}}
etc
#2022-12-1119:16lilactownthat might work. I'm trying to figure out how to disable the linter for
error: a number is not a function
#2022-12-1119:19borkdudeMaybe enable this one: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#show-linter-name-in-message#2022-12-1119:19borkdudethen you can see the keyword in the message#2022-12-1119:20lilactownah great! 😄#2022-12-1119:21lilactown
{:config-in-call
 {town.lilac.mogget/eval
  {:linters {:unresolved-symbol {:level :off}
             :invalid-arity {:level :off}
             :private-call {:level :off}
             :not-a-function {:level :off}}}}}
works great 🙂 thank you for the help!
#2022-12-1119:22borkdudeIs this about an eval macro that gets an unquoted expression?#2022-12-1119:22lilactownyeah#2022-12-1119:23lilactownI'm writing a little interpreter for a Factor-like language, that uses EDN#2022-12-1119:23borkdudewhy not use a quoted expression (even if it's a macro)?#2022-12-1119:24borkdudeclj-kondo will soon get support for linting inside quoted expressions (so navigation, etc work, but all warnings disabled)#2022-12-1119:24lilactownI didn't really think too hard about it#2022-12-1119:26lilactownit just seemed nice to be able to type
(eval 1 (inc) (inc) bi) ;; => [2 2]
without an extra set of parens & a quote
#2022-12-1119:27borkdudeyou could also write a hook for this which expands into a quoted form and a vector carrying the expressions ;)#2022-12-1119:27borkdudeanyway, doesn't really matter#2022-12-1119:28lilactownyeah, I might write my own custom hook for it later if I get really in the weeds. just wanted a quick way to turn it off so I could find the actual bugs in my code 😛#2022-12-1119:31lilactownhere's day 1 of AoC in my little language 😄
"1000
2000
3000

4000

5000
6000

7000
8000
9000

10000"

#"\n" str/split
(parse-long) map
(nil?) partition-with
(0 (+) reduce) map

;; part 1
(0 (max) reduce)

;; part 2
(sort reverse 3 take 0 (+) reduce)
bi
#2022-12-1119:32borkdudeit's a stack based language or so?#2022-12-1119:32lilactownthat's right#2022-12-1119:32lilactownI was doing AoC in https://factorcode.org and got inspired to make one myself#2022-12-1119:32borkdude:-)#2022-12-1214:06frankitoxHello 👋 is there any way to print clj-kondo's config? I'm trying to debug a difference of linting between local and CI#2022-12-1214:07borkdude@U3UFFB420 You can if you use clj-kondo programmatically
(clj-kondo.core/run! ...)
returns the effective :config
#2022-12-1214:08frankitoxOhh that's great! thank you 😄#2022-12-1216:49frankitoxTurned out the fix was to do rm -r .clj-kondo/.cache#2022-12-1217:52frankitoxI'm getting an unused value from this code (second line):
(let [x 1]
  (pmap some-effectul-fn! x)
  (inc x))
Is this a bug? :thinking_face:
#2022-12-1217:56hiredmanit is a bug in the code, pmap is lazy#2022-12-1217:57hiredman
user=> (doc pmap)
-------------------------
clojure.core/pmap
([f coll] [f coll & colls])
  Like map, except f is applied in parallel. Semi-lazy in that the
  parallel computation stays ahead of the consumption, but doesn't
  realize the entire result unless required. Only useful for
  computationally intensive functions where the time of f dominates
  the coordination overhead.
nil
user=>
#2022-12-1218:07skylizeThe value returned by (pmap some-effectful-fn~ x) is dumped into nowhere, neither assigned to anything nor returned by the enclosing let. That is the "value" that clj-kondo sees as "unused".#2022-12-1218:07hiredmanright#2022-12-1218:09hiredmanand if you don't force the lazy value of the pmap, it won't run completely, meaning some-effectful-fn won't be run for each input to pmap#2022-12-1218:09frankitoxWell, I'm not sure what magic is going on in the linter but if I do
(let [x 1]
  (doall
    (pmap some-effectul-fn! x))
  (inc x))
It doesn't yell to me anymore
#2022-12-1218:09hiredmanit is the same issue if you replace pmap with map, and map is lazy#2022-12-1218:10hiredmanit is more insidious of a bug with pmap, because pmap is only sort of lazy, so in testing with small inputs it may look like everything gets processed#2022-12-1218:10frankitoxRight, thanks for the observation! Gotta keep an eye on lazy code, I tend to forget it exists#2022-12-1218:10hiredmanbut in production with larger inputs, only the first 32 or whatever are processed#2022-12-1218:11skylizedo (or doall) implies likely side-effects. I presume that clj-kondo has incorporated that implication, to not bug you about the unused value in a do block.#2022-12-1218:12hiredmanpmap is also just not great in general#2022-12-1218:14frankitoxOh, why is that? Or what the alternative would be?#2022-12-1218:14Noah BogartIs there a better "pmap", hiredman?#2022-12-1218:17hiredmanit depends, if you don't care about the results on the pmap (like above) then use an executor directly#2022-12-1218:18hiredmanthere are libraries that try to provide a better version of something like pmap, but I have never used them#2022-12-1218:21hiredmanpmap is built as a way to parallelize computational expensive lazy seqs, not as a way to parallelize io operations#2022-12-1218:22hiredmanbut using it to parallelize io is what people try to do with it#2022-12-1218:23hiredmanand the combination of laziness + parallelism is not great for io#2022-12-1218:25Noah BogartAh that's interesting, I never put together that the focus is on parallelizing lazy seqs as the primary goal, even tho looking at the docs now it seems somewhat obvious lol#2022-12-1219:00frankitoxThat's what I was doing 😅 thank you for the advice#2022-12-1219:07hiredmanyou are in good company, it seems like pretty much everyone's first reaction to pmap is "great, I can do these http requests in parallel"#2022-12-1219:38borkdudeGreat discussion everyone 👏#2022-12-1303:53Noah BogartOne of the things that linters in other language do is give each linter error a unique id so that errors can be easily searched and discovered. Has any thought been given to adding this to clj-kondo? #2022-12-1306:30borkdudeThis can be enabled via config, see docs #2022-12-1306:31borkdudeOn mobile now so can’t give you the link but it’s in config.md#2022-12-1311:51frankitoxMaybe you mean https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#show-linter-name-in-message?#2022-12-1311:51borkdudeyes#2022-12-1314:05Noah BogartThanks. I should have been more specific. Those are good for knowing the name of the linter, but they don't search well unless you're in the linters docs page and use "find in page"#2022-12-1314:06borkdudeyes, you get an id and you can search. isn't that what you described?#2022-12-1314:06Noah BogartI'm thinking something like Python's Flake8 rules: https://www.flake8rules.com/rules/E101.html#2022-12-1314:07borkdudeI prefer a name like :unused-binding over E101 to be honest#2022-12-1314:08Noah BogartHere's an example of what I've run into:#2022-12-1314:09Noah Bogartvs flake8:#2022-12-1314:10borkdudeSo this is more about SEO#2022-12-1314:11Noah Bogartyes. folks in my org have come to me saying, "i'm getting this error and googling it doesn't tell me what's wrong" so i have to say "go to the docs/linters.md file and search it there" which works but is less direct than imo is necessary#2022-12-1314:12Noah BogartMaybe this is just something that would be helped by having a stand alone clj-kondo website, with a single page per linter. that's a lot of work lol just trying to think through it#2022-12-1314:12borkdudewell, it's unfortunate that google doesn't find unused binding -> linters.md ;)#2022-12-1314:15borkdudeMaybe we could enable showing the name by default#2022-12-1314:15borkdudebut this wouldn't solve the SEO problem#2022-12-1314:17borkdudePerhaps it would help if we generated an HTML page like this: https://book.babashka.org/ I'm not sure if it's Github README vs HTML or something else#2022-12-1314:18Noah BogartYeah, sadly not. This isn't a requirement, of course, for example eslint doesn't use "unique ids" that are letters and numbers (https://eslint.org/docs/latest/rules/no-await-in-loop), neither does rubocop (https://docs.rubocop.org/rubocop/cops_lint.html#lintbooleansymbol), but those both have stand-alone websites that might help in this regard#2022-12-1314:20Noah BogartJust in case, I hope I don't sound like I'm demanding you build a whole new website for this, lol. If this is something you're interested in, I'm willing to put in work as well. (For example, https://github.com/clj-kondo/clj-kondo/pull/1805 from back in September.)#2022-12-1314:20borkdudecan you do a couple of searches for words in http://book.babashka.org to see if they show up properly in google?#2022-12-1314:22borkdudeI've done a poll recently about what people prefer: mkdocs material / antora vs the http://book.babashka.org there is now. People vastly preferred the single page that there is now. I've thought about moving clj-kondo docs to asciidoc and then using the same http://book.babashka.org layout (single page). It'd be good to see if this helps SEO too#2022-12-1314:22Noah Bogarteach of this points to the book site but doesn't point to the specific part of the page. frustrating#2022-12-1314:23borkdudewell, at least it shows up#2022-12-1314:24borkdudegoogle sometimes does send you to some context on a website right#2022-12-1314:24borkdudewell, at least you can do ctrl-f after you end up there after google#2022-12-1314:25borkdudewhy are .md pages on Github not indexed that well then?#2022-12-1314:26borkdudeThis seems pretty good#2022-12-1314:26Noah Bogarti mentioned eslint and rubocop earlier. eslint has specific pages for each rule while rubocop does not. "eslint no-await-in-loop" points to the specific linter page, while "rubocop lint/booleansymbol" points to the "lint cops" page (that contains all of the lint rules)#2022-12-1314:27borkdudeWell, I think people need at least to know about config.md and linters.md to get going and maybe they should just ... read some docs?#2022-12-1314:27Noah Bogartseems this is just how google indexes things then, and is not a game we should fall into playing lmao. if it's smart for clj-kondo's workflow to have individual pages then do it, but don't do it merely for the seo#2022-12-1314:27Noah BogartAgreed. I do think that a "clj-kondo book" like the babashka one would be overall helpful, but I don't think doing more than that is necessary#2022-12-1314:28borkdudecool, I was already planning on doing that#2022-12-1314:28Noah Bogartthanks for talking with me about this! i appreciate it#2022-12-1314:29borkdudeif you want to help out, feel free to "port" the docs to asciidoc (I used pandoc for this with bb) and then set something up (using the same stuff as babashka, asciidoctor) that generates an HTML page. Only if you want, no pressure#2022-12-1314:30Noah BogartI'll see if I can scrounge up some time to give that a try! sounds like fun#2022-12-1314:32borkdudethe babashka book stuff lives here: https://github.com/babashka/book#2022-12-1314:32borkdudebut I think for clj-kondo I'd like the docs stuff to just live in the clj-kondo repo itself still#2022-12-1314:33borkdudenot sure#2022-12-1314:33borkdudefeel free to to put something up in a separate repo#2022-12-1315:55seriogaThe link to the docs should be shown along with error message :-)#2022-12-1311:54niwinzIs this a known issue?: a unused require warning when used in CLJC file and the require is used only on CLJ part of code? I have tried the v2022.12.10 version and still hapens to us.#2022-12-1312:00frankitoxJust in case, have you tried running clj-kondo without the cache? rm -r .clj-kondo/.cache#2022-12-1312:04borkdudeYes, this is standard behavior. if you're only using the namespace in one "target" you should wrap it in a reader conditional.#2022-12-1312:05borkdudeelse it would be quite wasteful to include namespaces in a clojurescript bundle that aren't used right#2022-12-1312:06borkdudeThere is an issue to clarify the message that it only applies to one target#2022-12-1312:06niwinzthe case is: i have a function that uses a macro in :clj condition but does not uses it on :cljs#2022-12-1312:07niwinzI'm not using it in both because the underlying implementation is different, and one raises exceptions and the other no, so this is a legitimate use in my opinion#2022-12-1312:08borkdudecan you make a full repro, in order for me to understand and give you better help?#2022-12-1312:08borkdudein the form of a .cljc file that I can lint locally#2022-12-1312:09niwinzhttps://github.com/penpot/penpot/blob/develop/common/src/app/common/geom/shapes/transforms.cljc#L165#2022-12-1312:10niwinzIf this not makes it clear, I can try to make a little repro#2022-12-1312:10niwinzthe ex/ignoring is a macro that just ignores exception and returns nil, it is used in one target but not in other#2022-12-1312:11borkdudeso what happens if you do (:require #?(:clj [ex.ignoring :as ex]))?#2022-12-1312:12niwinzyou mean include the require also in the condition, hmm, you right, I have not considered it :S#2022-12-1312:12borkdudeyes#2022-12-1312:13niwinzok, so sorry for this dumb quiestion then. didn't considered this obvious solution#2022-12-1312:13borkdudeno problem :)#2022-12-1502:40Lyn HeadleyCan clj-kondo "learn" by reading locally defined specs and inferring lint rules from them?#2022-12-1506:57borkdudeKind of: • https://github.com/clj-kondo/inspector (only a proof of concept) • https://github.com/metosin/malli#clj-kondo#2022-12-1516:38Matthew DowneyIs there a way to run clj-kondo.main from a babashka task? I know I can run clj-kondo https://github.com/clj-kondo/clj-kondo/blob/master/doc/jvm.md or as a https://github.com/clj-kondo/clj-kondo#babashka-pod, but from what I can tell the pod doesn't include the code in main. Ideally I'd be able to bb lint and have it replicate the behavior of clj-kondo --lint src, without the need to install the binary.#2022-12-1600:52borkdude@UP7RM6935 You can use the pod to 1) install the binary for you and 2) call clj-kondo's API programmatically: (clj-kondo/run! {:lint ["src"]}) + clj-kondo/print! is the equivalent#2022-12-1601:33Matthew DowneyOh wow thank you, that was easy 🙂#2022-12-1601:34Matthew Downey(For anyone else: I just merged this into bb.edn)
{:pods {clj-kondo/clj-kondo {:version "2022.12.10"}}
 :tasks {:requires ([pod.borkdude.clj-kondo :as clj-kondo])
         lint (clj-kondo/print! (clj-kondo/run! {:lint ["src"]}))}}
#2022-12-1519:06ericdalloWould be valid to have a new linter that warns about functions with lots of arity? example:
(my-function a b c d e f g) ;; too-many-arguments - my-funciton should have at most 4 args
#2022-12-1519:10ericdalloAt Nubank it's pretty common to see calls passing components like:
(do-something my-data producer consumer http metrics)
where we'd prefer
(do-something my-data components) ;; components is a map with all those components
#2022-12-1600:50borkdudeSure!#2022-12-1600:50borkdude:max-fn-arity linter?#2022-12-1600:51ericdallosounds good#2022-12-1801:42skylizeHow do I completely ignore a whole folder?#2022-12-1810:36borkdudeYou can do this in two ways: only explicitly lint the folders you want to lint: clj-kondo --lint src/foo src/bar or configure {:output {:exclude-files ["regex"]}}#2022-12-1816:31seriogaCan we use specific configuration to expression like
#_{:clj-kondo/config {}}
#2022-12-1816:33seriogaI don't like an idea to completely disable :shadowed-linter for expression but want to configure :exclude instead...#2022-12-1816:36seriogaWell, the silly attempt did not work 🙂
(defn declare-type
  #_{:clj-kondo/config {:linters {:shadowed-var {:exclude [type]}}}}
  [type {:keys [as-handler, as-wrapper, type-alias]}]
#2022-12-1816:52borkdudeHave you tried config-in-call?#2022-12-1816:55seriogaI did not. This is in config.edn? Too far from expression itself, can be easily missed in refactoring...#2022-12-1817:16seriogaI can create a feature request 😉#2022-12-1819:24borkdude@U0HJNJWJH Feel free to create an issue with a good use case of this#2022-12-1816:33seriogaI don't like an idea to completely disable :shadowed-linter for expression but want to configure :exclude instead...#2022-12-1816:36seriogaWell, the silly attempt did not work 🙂
(defn declare-type
  #_{:clj-kondo/config {:linters {:shadowed-var {:exclude [type]}}}}
  [type {:keys [as-handler, as-wrapper, type-alias]}]
#2022-12-2007:38mkvlrdoes someone have a github workflow to install an unreleased build of clj-kondo?#2022-12-2008:30borkdudeTwo ways: • Use clj-kondo as a git dependency • Download a binary from one of the builds#2022-12-2010:16borkdudeI could make a --dev-build flag to install with the clj-kondo install script maybe, would take a couple of hours of work#2022-12-2010:16borkdudebabashka install script now supports that#2022-12-2011:49mkvlr@U04V15CAJ awesome, thank you!#2022-12-2013:02mkvlrthis one?#2022-12-2013:02mkvlrhttps://github.com/clj-kondo/clj-kondo/blob/master/doc/install.md#2022-12-2013:13borkdudeyes, but I was saying that the babashka install script supports --dev-build, the clj-kondo script doesn't yet#2022-12-2013:13borkdude(just to be clear)#2022-12-2013:16mkvlrwhere can I get that?#2022-12-2013:17borkdudedefine "that"?#2022-12-2013:18borkdudeWhat I mean is, babashka supports installing a dev build of babashka in its install script#2022-12-2013:19mkvlrah ok, then I misunderstood#2022-12-2013:19borkdudefor now it's probably easiest to link to a amd linux binary from a recent circleci build#2022-12-2013:20mkvlrdo you have plans to do a release soon again maybe?#2022-12-2013:24borkdudeI aim for a monthly release since it's a bit of a hassle to release and if I'll do one, the high priority tickets here have to get fixed first: https://github.com/clj-kondo/clj-kondo/projects/1 So I think it's best to either use the git dep or download the pre-built dep from circleci or implement the --dev-build option#2022-12-2013:25borkdudeThe only two changes so far are https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#unreleased Compare to the other releases which are often a bit more substantial#2022-12-2013:26mkvlralright, I’ll try one of those options#2022-12-2013:28borkdude@mkvlr This link should be good: https://output.circle-artifacts.com/output/job/5e6d17d2-f3f3-4123-a521-96639ced7d8b/artifacts/0/release/clj-kondo-2022.12.11-SNAPSHOT-linux-static-amd64.zip#2022-12-2013:28borkdudeThe download is valid for 30 days or so but by the time it invalidates, there will be a new clj-kondo release#2022-12-2013:58mkvlr🎉#2022-12-2007:40mkvlris there a way to allow :refer-all but only in test namespaces?#2022-12-2008:31borkdudeYou can do this by making a namespace group based on the name of the namespaces or pattern of the file + config-in-ns https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#namespace-groups#2022-12-2008:31borkdudeOr by separately linting the test dirs with an additional --config argument#2022-12-2008:32mkvlrah nice, thanks#2022-12-2008:32borkdudeOr if this is only for clojure.test :refer :all then you can configure that in config.edn#2022-12-2008:32mkvlryep, I did that#2022-12-2008:33mkvlrfor clojure.test it works nicely#2022-12-2008:33mkvlrexcept for one case where it doesn’t, curious if you see something wrong there, posted it in the ductile channel#2022-12-2008:33borkdude:refer :all is making things a lot more difficult for clj-kondo and static analysis in general, problems are expected with multiple of those#2022-12-2008:41mkvlrdoes that also apply to clojure.test or is there special handling for it?#2022-12-2008:43mkvlr> problems are expected with multiple of those do you mean if referred names overlap or in general? Since kondo does analyze the required namespaces can’t you infer where a name is coming from?#2022-12-2008:46borkdudeI'll take a look in the ductile channel in a bit#2022-12-2009:25borkdudeI'm not sure what exactly I should be looking at#2022-12-2015:12Eric ScottSo I made a silly error in my deps.edn file that looks like this:
{:deps {<library> {:mvn/version ... :exclusions [[nested-too-deep]]}, ...}...}
It showed up as a cryptic stack trace, and seemed funny that this wasn't flagged as a spec viloation. I asked about this on #C03S1KBA2, and they suggested that clj-kondo might be able to catch this. Entering
clojure -M:kondo --lint deps.edn
Does not flag an error, but obvious syntax errors do get flagged. As I said, I think this is more of a spec violation. Am I using the wrong incantation?
#2022-12-2015:14borkdudeThis specific case hasn't been covered by clj-kondo, but feel free to post an issue about it#2022-12-2015:15Eric ScottThanks!#2022-12-2015:20borkdude@ericdallo Would you mind bumping clj-kondo on clojure-lsp master, so @phillipmates and some other can install the nightly with some (for them) relevant changes? cc @mkvlr#2022-12-2021:50ericdalloSure#2022-12-2021:51ericdalloBump to stable clj-kondo or a nightly specific kondo version?#2022-12-2021:51borkdudenightly, most recent version on master#2022-12-2021:51ericdallo👍#2022-12-2021:54ericdalloDone#2022-12-2021:54ericdalloShould be available on #C032YH7P0R2 soon#2022-12-2922:25jkxyzIs there a built-in hook similar to clj-kondo.lint-as/def-catch-all which treats the first arg as a var name and lints the rest of the args as if it's a normal function call? I feel like I run into these kinds of macros pretty often and def-catch-all isn't ideal because it seems to disable most linters. instaparse.core/defparser and devcards.core/defcard come to mind. They just take a name and some data.#2022-12-2922:29borkdude> which treats the first arg as a var name and lints the rest of the args as if it's a normal function call? In that case you can use {:lint-as {... clojure.core/def}}#2022-12-2922:30jkxyzWill that work for an arbitrary number of arguments?#2022-12-2922:33jkxyzWell it seems to work, thanks! I was thinking that :lint-as would make it throw an invalid-arity error when the args don't match clojure.core/def#2022-12-2922:34borkdudeI hadn't thought about that, but if it works... :)#2023-01-0120:58millettjonThe https://www.unison-lang.org/ language reminded me of the old https://github.com/Datomic/codeq project. I am wondering if there is any interest in having clj-kondo work off a codeq style data store maybe backed by https://github.com/replikativ/datahike or https://github.com/threatgrid/asami.#2023-01-0208:53borkdudeThe clj-kondo https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md can be stored in such a data store. In fact clojure-lsp has been doing this in datalevin for a while, but now it's using transit (like clj-kondo itself). Once you know the queries you're going to do you can optimize for that in your storage format. Clj-kondo tries to conservative in the amount of dependencies involved, so it's not using datahike or asami, just transit files.#2023-01-0214:12millettjonThanks. I didn't know clojure-lsp was using datalevin. It seems like a global, immutable, semantic, content addressable code store would benefit every level of the tool chain. I am wondering what are the possible incremental steps to enable it in the various tools. I totally get keeping clj-kondo lightweight with minimal deps. Maybe there is a setup where a standalone code store is available, and tooling could optionally hook into it to gain additional super powers?#2023-01-0308:06jeroenvandijk@U071T1PT6 I believe you are right about the content addressable code store. I think clojure-lsp and clj-kondo and others are “small” incremental steps towards this (in my opinion). Recently someone coined a related initiative with #C03FF6W62A3 Not sure where this is going, but you might find some more ideas there. I also thought of https://clojurians.slack.com/archives/C03FF6W62A3/p1653908127822239?thread_ts=1653905543.461139&amp;cid=C03FF6W62A3#2023-01-0314:17millettjon@U0FT7SRLP Definitely relevant. Thanks for the references.#2023-01-0213:10Yehonathan SharvitIs there a way to configure lein clj-kondo so that it exits with 0 when there are only warnings?#2023-01-0213:10borkdudeIn general, you can configure this with --fail-level error#2023-01-0213:10Yehonathan SharvitNice!#2023-01-0213:16Yehonathan SharvitIs there a way to set fail-level inside project.clj somehow?#2023-01-0213:17borkdude@U0L91U7A8 I think you can do it like this: https://github.com/clj-kondo/lein-clj-kondo#config with :fail-level :error#2023-01-0213:18borkdudeI'm not entirely sure, I'll check#2023-01-0213:18borkdudeyou can also do it like this I guess? https://github.com/clj-kondo/lein-clj-kondo#aliases#2023-01-0213:19Yehonathan SharvitAnd as part of .clj-kondo/config.edn ?#2023-01-0213:20borkdudeIt's not part of the config.edn, but of the CLI invocation or library invocation.#2023-01-0213:20borkdudeYou can of course use clj-kondo programmatically if that's easier for you#2023-01-0213:20borkdude
(-> (clj-kondo.core/run! {:fail-level :error :lint ["src" "test"]}) (clj-kondo.core/print!))
#2023-01-0213:21borkdudeand then check the :errors yourself and throw#2023-01-0213:21Yehonathan SharvitI prefer to have it inside project.clj . But it doesn't seem to work 😞#2023-01-0213:21borkdudedid you try aliases like described in the README?#2023-01-0213:22borkdudewhat clj-kondo version are you using#2023-01-0213:29Yehonathan SharvitWith aliases, it works#2023-01-0213:30Yehonathan SharvitBut not with ;config under :clj-kondo in project.clj#2023-01-0213:31borkdude:fail-level isn't supposed to be inside :config#2023-01-0213:32borkdudeI think lein clj-kondo doesn't pick up on settings outside of config though so you'll have to go with aliases - is this a problem?#2023-01-0214:00Yehonathan SharvitLet me see...#2023-01-0214:45Yehonathan SharvitIt is a bit problematic in our case as we have a kondo-lint alias defined in a parent project. I'd prefer not overriding it in the child project.#2023-01-0214:52borkdudeThen use a different name?#2023-01-0215:10borkdude@U0L91U7A8 Should be supported now with version 0.2.3#2023-01-0215:13borkdudeUse it like this:
{:config ... :fail-level :error}
#2023-01-0215:16borkdudesorry, something went wrong, it should be 0.2.4#2023-01-0215:27Yehonathan SharvitPerfect!#2023-01-0215:27Yehonathan SharvitI cannot use a different name for kondo-lint alias because it is used by another alias 😱#2023-01-0514:52Proctoris there a way to mark a form as critical? the opposite of #_:clj-kondo/ignore? e.g. some temp debug stuff that should not be checked in (to trunk at least), and could be nice when I write it to be able to mark it at the same time to have kondo flag it as critical#2023-01-0515:23borkdudeCan you make a full example, in order for me to understand better?#2023-01-0515:59jakemccThis is git specific but I use a git pre-commit hook to have a language agnostic way of letting me mark a specific line as "hey, computer don't let me accidentally commit this change" I've written about https://jakemccrary.com/blog/2015/05/31/use-git-pre-commit-hooks-to-stop-unwanted-commits/. It looks like I've slightly tweaked the pre-commit hook since writing that article and the latest version can be found https://github.com/jakemcc/dotfiles/blob/master/git-templates/hooks/pre-commit#2023-01-0516:15ProctorI am doing some println/logging debugging of raw api call results which contain secrets (db credentials, api tokens, etc) when doing local development (because the upstream api looks broken). Since those would be no-nos to have to have in production-like environments in the logs thought maybe marking them as critical might be a way to make sure that those would never creep in#2023-01-0516:17Proctorthinking almost as a hard-lined “TODO” resolution check#2023-01-0516:19Proctorwhere it makes sense to let it make it into local commits for a working branch, but could be halted by a CI check for getting into trunk#2023-01-0516:20Proctorusing CI as being the latest worse case prevention, but even a local check of critical issues when doing final prep for a branch#2023-01-0516:45borkdude@US03ZP2F5 We have discouraged-var for specific forbidden var usages Perhaps you can make an "identity" macro like:
(defmacro dont-do-this [x] x)
and then add this to the discouraged-var linter and wrap calls that should not be used in there
#2023-01-0516:47Proctornice#2023-01-0521:59Damien KickI am writing code that makes use of core.logic in Emacs with clj-kondo doing linting, and it keeps complaining about the binding forms ...
(l/run 3 [q]
    (l/conde
     [(l/== q [[:first "Damien"] [:middle "Robert"] [:last "Kick"]])]
     [(l/== q [[:first "Damien"] [:middle nil] [:last "Kick"]])]
     [(l/== q [[:nickname "D'amy"]])])
    (name!? q))
... gives me ...
{:tag :a, :attrs {:href "/cdn-cgi/l/email-protection", :class "__cf_email__", :data-cfemail "56323d3f353d671632393839203738"}, :content ("[email protected]")}
These are not typical let-like binding forms because they are not of the form name value but rather only just name. How can I tell clj-kondo stop complaining about unresolved symbols? Thanks
#2023-01-0522:01borkdudeThere are various ways to deal with this: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#unrecognized-macros#2023-01-0522:02borkdudeI think writing a hook for it would be the best option. Then we could maybe host those here: https://github.com/clj-kondo/configs So everyone could use them#2023-01-0522:09borkdudeBut the quick and dirty way would be to just silence the unresolved var linter for l/run#2023-01-0523:05Ben LiebermanHow do I suppress/disable a lint on something like Potemkin's def-derived-map? I know about the :lint-as key in config.edn but I wasn't sure if this was a) the right approach or b) how exactly to do it if it is.#2023-01-0523:09borkdudepotemkin already has a clj-kondo configuration that you can import: https://github.com/clj-commons/potemkin/blob/master/resources/clj-kondo.exports/potemkin/potemkin/config.edn#2023-01-0523:09Ben Liebermangreat, thanks @U04V15CAJ!#2023-01-0523:10borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#importing#2023-01-0523:12borkdudeif you're using clojure-lsp, this importing goes automatically#2023-01-0523:19Ben Liebermanhmm, I am using clojure-lsp. are there any LSP-specific steps I need to take here or no?#2023-01-0523:21borkdudeMaybe @UKFSJSM38 can chime in. I’m about to sleep now :)#2023-01-0523:22Ben LiebermanNo worries, thank you!#2023-01-0523:24ericdalloclojure-lsp when calling clj-kondo will pass the --copy-configs by default, so you only need something like this in your .clj-kondo/config.edn
{:config-paths ["potemkin/potemkin"]} 
#2023-01-0523:24ericdalloThis way, clj-kondo will recognize those copied folders and use those configs during linting#2023-01-0523:30Ben LiebermanI added that to my config.edn and now the "quick fix" gives me a drop down menu to tell LSP to lint the selection as one of a number of clojure.core vars, but clicking on any of them does not seem to do anything?#2023-01-0523:31Ben LiebermanI did however put this in my project-level config, should it be in the global clj-kondo config?#2023-01-0523:39Ben Liebermannvm, got it!#2023-01-0621:46phronmophobicI'm using clj-kondo to statically analyze projects for dewey. I'm interested in adding custom analyzers. It seems like there's no way to add additional analyzers. Is that right? I see that it's possible to add hooks and that hooks can emit findings, but it doesn't seem like there's a way to emit analyses? Maybe there's not much of a difference between "findings" and "analysis results"? As an example, I'm interested in extracting all the spec definitions within a project.#2023-01-0622:08borkdudeI think clojure.spec more runtime oriented than amenable to static analysis. I've tried to cross that bridge here a bit: https://github.com/clj-kondo/inspector#2023-01-0622:11borkdudeWe could make the SCI environment pluggable so you can do anything you need in your hooks, e.g. spit out stuff to a database or whatever. But you could experiment with this in a fork to start, I think#2023-01-0622:11phronmophobicI think it would be valuable just to have the keyword for each spec and the definition form#2023-01-0622:12borkdudewe do have those keywords for clojure.spec already, I think there's a defined-by clojure.spec.alpha key on them in the keywords analysis or so#2023-01-0622:12phronmophobicand doc strings once there’s support#2023-01-0622:12borkdudebut there is no definition yet#2023-01-0622:13borkdudethis issue might be related: https://github.com/clj-kondo/clj-kondo/issues/1268#2023-01-0622:13phronmophobicI’m generally interested in custom analyzers. The spec defs is just an example #2023-01-0622:14borkdudethere is some custom analysis available, you can add :context to something and this could be anything - I'd have to look this up how it works exactly#2023-01-0622:15borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#context-data#2023-01-0622:16phronmophobiccool! so I would create a hook and return some data in a :context key?#2023-01-0622:17borkdudeyes. you would add to the keyword some :context {:my-thing "blob"} and if you then request analysis with {:content [:my-thing]} or {:context true} , the keyword will appear with that data in the analysis#2023-01-0622:19borkdudethis was more a way to add arbitrary properties to existing analysis, but I think we could also allow inserting whatever analysis you like to see#2023-01-0914:38licht1steinI have this very strange situation. When I lint with clj-kondo the entire project, it gives me lots of redefined var errors. But when I lint any of the subdirectories — it says everything is fine. And there are no redefined vars: First screenshot is linting a subdirectory. Second is linting . On CI everything is fine, there are not linting errors with the same launch params.#2023-01-0914:42borkdudecan you make a repro so I (or someone else) has something to work with?#2023-01-0918:44licht1steinI have no idea how to reproduce it, since it works correctly even on CI...#2023-01-0918:45borkdudePerhaps if you lint twice, it starts to happen?#2023-01-0922:25licht1steinI've got linting on a pre-push hook, but I have no-cache setting on#2023-01-0922:26borkdudebut can you reproduce it locally, by linting twice with the cache on?#2023-01-1307:57licht1steinIt reproduces every time#2023-01-1307:58borkdudeI will need a repro to look into it#2023-01-1008:51Jakub Holý (HolyJak)Hello! What is the recommended way of dealing with libs that generate their fns from some data / other ns, such as https://github.com/expez/superstring/blob/master/src/superstring/core.clj#L35-L36 ?#2023-01-1009:00borkdudeIt seems that defalias is similar to def so you can use:
{:lint-as {foobar/defalias clojure.core/def}}
#2023-01-1009:01borkdudeit seems that (alias-ns clojure.string) is the same as (:require [clojure.string :refer :all]) - why invent a new syntax for this#2023-01-1009:02borkdudeah yeah, I see, they are creating vars in their namespace to re-export clojure.string#2023-01-1009:03borkdudethere's not much that you can do about this in clj-kondo, except that you can :exclude some vars in the unresolved var linter#2023-01-1009:03borkdude(https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-var)#2023-01-1009:44Jakub Holý (HolyJak)Thank you!#2023-01-1009:45Jakub Holý (HolyJak)I though that perhaps there was a way to tell Kondo that superstring.core/join etc. exists and is the same as clojure.core/string etc. Ok, we will just exclude this lint check for the ns then.#2023-01-1009:45borkdudeI think you might just as well use clojure.string directly ;)#2023-01-1012:53wilkerlucioone way is to have an explicit declare for all the things being generated, Fulcro uses this approach for the DOM namespace: https://github.com/fulcrologic/fulcro/blob/main/src/main/com/fulcrologic/fulcro/dom.cljs#L17-L30#2023-01-1012:54borkdudeindeed#2023-01-1012:55borkdudeanother way to "fix" this is to use clj-easy/stub https://github.com/clj-easy/stub which can generate stub namespaces with vars detected at runtime. Then you need to add this to your "lint" path so clj-kondo will pick up on those stubs#2023-01-1012:56borkdudealso see https://clojure-lsp.io/settings/#stub-generation#2023-01-1012:56borkdudebut the declare approach is the most robust I'd say#2023-01-1012:57wilkerluciowhat I like about declare is that it will work with any tool (like LSP, but also Cursive)#2023-01-1012:58borkdudeyes, that's what I mean with "robust" :)#2023-01-1012:58borkdudeperhaps the super-string maintainers can be convinced to add it#2023-01-1012:59wilkerlucioyup, others have been, like on the CSK library: https://github.com/clj-commons/camel-snake-kebab/pull/54/files#2023-01-1012:59borkdudenice!#2023-01-1110:35Jakub Holý (HolyJak)awesome, thanks! I will talk to the maintainer#2023-01-1522:52Jakub Holý (HolyJak)FYI superstring has a new release with the declare s. Thanks for the tip!#2023-01-1118:48borkdudeI wonder if clj-kondo should report (:require [my-namespace :as-alias mns]) as unused if the alias isn't used anywhere - there is no harm in this unused namespace since it doesn't really load the namespace? The reason I'm bringing this up is because in clerk, the following situation arises:
(:require [nextjournal.clerk.viewer :as-alias v])

'(fn [x] (v/html [:div x]))
The alias isn't really used, but clj-kondo exports analysis about the quoted symbol v/html along with information about what namespace might be targeted with it, so clojure-lsp can navigate to nextjournal.clerk.viewer/html when you navigate to that symbol. The already supported way of doing this is using syntax-quote, but writing functions in syntax-quote isn't always that convenient / nice to read? But from the perspective of clj-kondo, the alias v isn't really used since it only occurs in a quote. Hence you will get an unused namespace warning. 🧵
#2023-01-1118:57skylize> there is no harm in this unused namespace since it doesn't really load the namespace? > Wow. Really? So what happens when/if the quoted expression gets evaluated later? Does the namespace get loaded late as part of that evaluation?#2023-01-1118:58borkdudeI think the :as-alias is a syntactic sugar for writing:
(alias 'v (create-ns 'nextjournal.clerk.viewer))
which clj-kondo never warned about, so with that reasoning, it might make sense to not warn
#2023-01-1118:58borkdudeIn this case, the quoted expression gets evaluated on the front-end#2023-01-1118:58borkdudein a SCI environment that has these aliases#2023-01-1119:09ericdalloI agree it's unused, but This will make clojure-lsp remove that require when cleaning the ns, making that navigation of the symbol probably not work right?#2023-01-1119:18borkdudeindeed#2023-01-1119:18borkdudeI guess people could also use #_:clj-kondo/ignore#2023-01-1119:25borkdudebut clojure-lsp still removes the namespace in that case... why, clj-kondo didn't report it?#2023-01-1119:25borkdudeoh, no, it removes the #_clj-kondo/ignore#2023-01-1119:26borkdudeanyway, that's a different issue I guess
#2023-01-1119:33borkdudeI'll remove the warning for as-aliased namespace and if desired, I can make an option later to re-enable this#2023-01-1211:34ericdalloSounds good#2023-01-1211:36borkdudealready done on master#2023-01-1215:00borkdude#2023-01-1217:41ericdalloI'd like to bring some numbers to you @borkdude about clojure-lsp linter (clj-kondo used under the hood) adoption in Nubank services, there are more than 1000 services/libraries using clojure-lsp format, clean-ns and diagnostics, a really good success case for both libs clj-kondo ❤️ clojure-lsp#2023-01-1220:20nathanmarz@borkdude how would I go about adding a linting hook for calls to new?#2023-01-1220:21borkdudeyou can add a hook for clojure.core/new#2023-01-1220:26nathanmarzthanks, that worked great#2023-01-1223:05nathanmarzkondo seems to have different behavior for (Foo.) callsites vs. (new Foo)#2023-01-1223:06nathanmarzboth are caught by clojure.core/new hook, but the former doesn't have any metadata and doesn't respect :clj-kondo/ignore annotations#2023-01-1307:36borkdudeCan you post an issue?#2023-01-1319:32nathanmarzSure https://github.com/clj-kondo/clj-kondo/issues/1944#2023-01-1619:38borkdudev2021.07.28 is quite old, can you upgrade?#2023-01-1316:05pmooserI've just started using clojure-lsp, which uses clj-kondo for its linting ... and I've noticed it will emit warnings and errors for code inside of comment blocks. Is there any way to disable this globally? I tend to use comment blocks for certain kinds of examples and seeing a bunch of warnings about unused vars is a little distracting.#2023-01-1316:06lispycloudshttps://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#ignore-the-contents-of-comment-forms#2023-01-1316:07borkdude@U07VBK5CJ I recommend using :config-in-comment to disable some, but not all linters#2023-01-1316:07borkdudeexample here: https://github.com/nextjournal/clerk/blob/d978d0ca6cb7b10cf1a0c0f370cdba6e096551e3/.clj-kondo/config.edn#L29-L36#2023-01-1316:07pmooserOk, but I am still impressed that the option already exists! I will take a look. Thank you both for the replies !#2023-01-1416:02robert-stuttaford
:config-in-comment {:linters {:unresolved-namespace         {:level :off}
                               :unresolved-symbol            {:level :off}
                               :unresolved-var               {:level :off}
                               :duplicate-require            {:level :off}
                               :unsorted-required-namespaces {:level :off}
                               :unused-namespace             {:level :off}
                               :unused-binding               {:level :off}}}
we use 'rich comments' extensively, this is our kondo config
#2023-01-1416:03robert-stuttafordcurious, a question about linting cljc where a binding is used in only one target... is this the lowest-friction way to deal with unused-binding if you want zero warnings?
#_{:clj-kondo/ignore [:unused-binding]} ;; for `props`
(defui action-link-button [{:keys [href title] :as props}]
  ($ :a {:href href
         #
#2023-01-1416:05borkdudeyes, or :as #?(:cljs props :clj _)#2023-01-1416:07robert-stuttafordglad i asked, didn't think of that trick!#2023-01-1416:54dominicmI'm linting a macro that's intended for use with cljs. It expands to contain something like:
;; bar.clj
(ns foo.bar)

(defmacro baz
  []
  `(some.other.ns/bish))
Then to make it available, I do:
;; bar.cljs
(ns foo.bar
  (:require some.other.ns)
  (:require-macros [foo.bar :refer [baz]]))
But kondo is insistent that when I use the macro that I need to require some.other.ns.
;; app.cljs
(ns app
  (:require [foo.bar :refer [baz]]))

(baz)
Is there some way I can have my analysis hook indicate that some.other.ns will be loaded so it isn't a problem?
#2023-01-1418:19borkdudeYou can write (list 'some.other.ns/bish)#2023-01-1418:19borkdudeor ~'some-other-ns/bish#2023-01-1420:22dominicmWon't that just quote the form, rather than indicate it's loaded?#2023-01-1420:28borkdudeYes, isn't that exactly what you want?#2023-01-1420:30dominicmThe form needs to be expanded so it can be analyzed. Just not for this symbol referring to a namespace that isn't required.#2023-01-1420:30borkdudeexactly#2023-01-1420:31dominicmI've missed the part where the form is sort of a fill in to get kondo to check that the code provided plays nicely in a threading macro with other code.#2023-01-1420:31dominicmSo I still want analyzed as if it works. But also, the require isn't missing, it's just done by the macro instead.#2023-01-1420:32borkdudeYou want to generate (some-thing.foobar/whatever 1) regardless of what your namespace aliases are. Then it's better to use single quote as this is unrelated to your namespace state. Either: (list 'something.foobar/whatever 1) or
`(~'something.foo/whatever 1)
does that
#2023-01-1420:33borkdudeor maybe I'm missing something. this is about macro usage?#2023-01-1420:33borkdudecan you maybe write a repro that I can inspect locally?#2023-01-1420:33dominicmI think you're missing something#2023-01-1420:33dominicmThis is for my hook analysis#2023-01-1420:33borkduderight#2023-01-1420:34dominicmBut in clojurescript, you have to refer to things by their full name from macros#2023-01-1420:34borkdudemaybe just require the namespace in the namespace where you're using the macro?#2023-01-1420:34dominicmThat leaks the abstraction though :)#2023-01-1420:35dominicmThat's a workaround, which is fine. But I'd like to drive through a solution#2023-01-1420:35borkdudeyou can configure :unresolved-namespace :exclude [your.generated.namespace]#2023-01-1420:35dominicmCan I do that just for a single nested form?#2023-01-1420:36borkdudeyou can do that with a combination of :config-in-call for the macro maybe#2023-01-1420:37borkdude
:config-in-call {your.ns/macro {:linters {:unresolved-namespace {:exclude [some-thing.foobar]}}}
#2023-01-1420:37dominicmI'd prefer that the user was warned if they wrote the fully qualified namespace without requiring it.#2023-01-1420:37dominicmI'd just like to ignore it in generated code#2023-01-1420:38borkdudethen maybe just not generate that namespace usage?#2023-01-1420:40dominicmBut I want kondo to analyze usage with it 😜 Eg, I want to generate (call.to.foo/bar for kondo to lint that the user supplied list isn't longer than the args that bar can take, etc.#2023-01-1420:41borkdudebut if your macro generates that namespace usage, shouldn't the user at least require that namespace themselves? or is this never the case?#2023-01-1420:41dominicmNever the case. The macro requires it for them.#2023-01-1420:41borkdudehow does a macro require namespaces for them?#2023-01-1420:42dominicmIt's required by the namespace the macro is defined in#2023-01-1420:44borkdudebut a macro runs in the JVM and generates CLJS code. the JVM cannot require CLJS code.#2023-01-1420:44dominicmThat's why the cljs namespace is there to do :require-macros. This is how cljs-compatible macros work.#2023-01-1420:45borkdudeBut in that case the user already requires this macro namespace and the require should already be present? Can you give me a real example that I can run that demonstrates the problem?#2023-01-1420:46dominicmBut I'm generating a call to a third namespace, not the namespace the macro is defined in.#2023-01-1420:46borkdudeok, and the cljs namespace is also loading that#2023-01-1420:46dominicmI can put one together, but I'm pretty tired for tonight.#2023-01-1420:46dominicmYeah, exactly 🙂#2023-01-1420:46borkdudeI get it#2023-01-1420:48borkdudeso the :config-in-call + :unresolved-namespace + :exclude should work but instead of :exclude we should have something like :already-loaded for namespace that are safely assumed to be loaded#2023-01-1420:49dominicmExactly. OR, we could allow to mark the "generated" code which only has some of the analysis applied to it.#2023-01-1420:50borkdudeI think we could change the meaning of :exclude to mean: this isn't unresolved, but already loaded globally#2023-01-1420:50borkdudethat would be the smallest change to support your use case#2023-01-1420:50dominicmAh#2023-01-1420:51borkdudeand "globally" can be less global with a combination of :config-in-call#2023-01-1420:51borkdudeissue welcome#2023-01-1518:55borkdudeNew (optional, off by default) linter on master: :def-fn - recommend using defn over def + fn or def + let + fn The benefits of those would be :arglists metadata and better stack traces. https://github.com/clj-kondo/clj-kondo/commit/51ccf596e42d7a4bc43af87ed2371d74d2059371#2023-01-1519:02borkdudeClarified the docs a little more: https://github.com/clj-kondo/clj-kondo/commit/4a6a989b4608d75bd9d0e38f43fa8c8e054914a1#2023-01-1609:44grahamcarlylethe new :aliased-namespace-var-usage is complaining when the as-alias is just used to refer to namespaced keywords in my project. I thought :as-alias was designed for that sort of usage?#2023-01-1609:48borkdude@U053YSSSJ Hmm, can you give a repro?#2023-01-1609:49borkdudeHmm, I see:
$ clj-kondo --lint - <<< '(ns foo (:require [bar :as-alias b])) ::b/dude'
<stdin>::: warning: Namespace only aliased but wasn't loaded: bar
linting took 35ms, errors: 0, warnings: 1
Yeah, that's no good. I'll fix it right away
#2023-01-1609:53grahamcarlylethanks, a nice demo of how to quickly reproduce too 🙂#2023-01-1609:56borkdudeFixed on master#2023-01-1609:56borkdude@UKFSJSM38 Please bump clj-kondo with this fix in clojure-lsp#2023-01-1611:57ericdalloSure, I can bump to latest kondo before next release#2023-01-1620:16borkdudeThis should be fixed in 2023.01.16 which I just released#2023-01-1614:37Colin P. HillIs there currently any way to configure :missing-docstring to ignore vars with :no-doc/`:skip-wiki`/etc?#2023-01-1614:39borkdudeNo, but I think that would be a great addition. Could you post an issue? (+ optionally a PR, don't feel pressured)#2023-01-1615:33Colin P. HillDone https://github.com/clj-kondo/clj-kondo/issues/1950#2023-01-1620:01borkdudehttps://github.com/clj-kondo/clj-kondo: static analyzer and linter for Clojure code that sparks joy 2023.01.16 • https://github.com/clj-kondo/clj-kondo/issues/1920: new linter :def-fn: warn when using fn inside def, or fn inside let inside def (https://github.com/andreyorst). • https://github.com/clj-kondo/clj-kondo/issues/1949: :aliased-namespace-var-usage gives erroneous output for keywords • Add test for https://github.com/clj-kondo/clj-kondo/issues/1944 (already worked) • Don't reload SCI namespace on every hook usage #2023-01-1620:04borkdude@UKFSJSM38 plz upgrade in clojure-lsp - especially the hook reloading should matter for performance if many hooks are used#2023-01-1620:04borkdudeaccidentally the hook code was reloaded every time the hook was used...#2023-01-1620:04ericdalloSure!#2023-01-1620:11borkdudeI recommend upgrading to 2023.01.16 if you're using many hooks since accidentally the SCI namespaces were always reloaded on every hook usage. Due to this: https://github.com/clj-kondo/clj-kondo/issues/1954#2023-01-1620:48souenzzoSeems that kondo do not support the deprecation of a one specific arity. Anyone else interested in it? echo '(defn foo ^:deprecated (^:deprecated []) ([x] x)) (foo)' | clj-kondo --lint -#2023-01-1620:50dpsuttonI don’t think that’s a thing for Clojure either:
user=> (defn foo ^:deprecated (^:deprecated []) ([x] x))
#'user/foo
user=> (meta #'foo)
{:arglists ([] [x]),
 :line 140,
 :column 1,
 :file "NO_SOURCE_PATH",
 :name foo,
 :ns #object[clojure.lang.Namespace "0x7a3eafcd" "user"]}
#2023-01-1620:51dpsuttonnote if you put the ^:deprecated on the var
user=> (defn ^:deprecated foo (^:deprecated []) ([x] x))
#'user/foo
user=> (meta #'foo)
{:deprecated true,
 :arglists ([] [x]),
 :line 142,
 :column 1,
 :file "NO_SOURCE_PATH",
 :name foo,
 :ns #object[clojure.lang.Namespace "0x7a3eafcd" "user"]}
#2023-01-1620:53souenzzoActually:
user=>  (defn foo (^:deprecated []) ([x] x))
#'user/foo
user=> (map meta (:arglists (meta #'foo)))
({:deprecated true} nil)
#2023-01-1711:32Alexis SchadHi there, I wanted to write a hook for defun (https://github.com/killme2008/defun) but it is actually a macro that produces valid clojure code (like all macros I guess?). Is there any way to expand the macro to tell clj-kondo the underlying syntax? How does clj-kondo handle the differences between the original syntax and the transformed one?#2023-01-1711:36borkdudeclj-kondo transforms code using the hook and then lints the expanded code#2023-01-1711:37borkdudeyou can provide a way simpler expansion than the original macro using :analyze-call or :macroexpand just something that clj-kondo understands, e.g. transform the keyword arguments into symbols#2023-01-1711:38borkdudeor just one argument _x or so#2023-01-1714:27Alexis SchadThanks! I don't really care if the transformed version is more complex if I don't have to write it, it seems easier to just use the macro itself but nvm. I did try to figure out how to do this manually, but I'm having a little trouble with recur. Here's the initial syntax:
(defun accum-defun
  ([0 ret] ret)
  ([n ret] (recur (dec n) (+ n ret)))
  ([n] (recur n 0)))
Here is what I produce:
(defn accum-defun [& args#]
  (let [ret (nth args# 1)]
    ret)
  (let [n (nth args# 0)
        ret (nth args# 1)]
    (recur (dec n) (+ n ret)))
  (let [n (nth args# 0)]
    (recur n 0)))
So I got a recur error: recur argument count mismatch (expected 1, got 2)" I can replace all underlying recur to the function name but I have to manage nested loop/fn in recursion. Is there an easier way or am I doing it right?
#2023-01-1714:45Alexis SchadIt seems to work like that, just checked for 'fn or 'loop to stop recursion if it is the value of the first child of a list node#2023-01-1715:30borkdudeif you have a varargs function, recur only takes 1 argument#2023-01-1719:20escherizeIs there a kondo hook for schema.core/defn? I’m looking through https://github.com/metosin/malli/blob/master/resources/clj-kondo/clj-kondo.exports/metosin/malli/config.edn#L1, and I can’t figure out where the schema.core/defn hook comes from. I thought they’d be in https://github.com/plumatic/schema/blob/master/resources/clj-kondo.exports/prismatic/schema/config.edn but it isnt there#2023-01-1719:21borkdudeThis is built into clj-kondo#2023-01-1719:23escherizeThanks. https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/schema.clj#2023-01-1719:24borkdudeThis predates hooks#2023-01-1719:24escherizeHow hard would it be to adapt this for malli.experimental/defn ?#2023-01-1719:25borkdudeyou can use :lint-as right?#2023-01-1719:26escherizeI believe that stopped working lately. Does this comment make sense? https://github.com/metabase/metabase/pull/27647/files#diff-b30ee307d9c92516f1f5b912532eb62cb13c00cc267ed51df7953e9c97fb6ae8R11-R13#2023-01-1719:26borkdudeI see. Are you working at metabase?#2023-01-1719:27escherizemu/defn has same shape as malli.experimental/defn. I am#2023-01-1719:27borkdudeI think it might be better if malli got dedicated hooks if the lint-as no longer works#2023-01-1719:28escherizeI think that’d be awesome#2023-01-1719:31escherizeas it is, malli is linting mx/defn as schema.core/defn. I am not sure but that may break too. https://github.com/metosin/malli/blob/master/resources/clj-kondo/clj-kondo.exports/metosin/malli/config.edn#L1#2023-01-1719:31borkdudeSo this will be a PR to metosin/malli then in their exported hooks. I think opening an issue with them would be best and I can help where needed. I also work for metabase on clj-kondo issues sometimes, so if this is a priority I can also do this under "their" time as well. cc @U11BV7MTK#2023-01-1720:18escherizeposted in #malli https://clojurians.slack.com/archives/CLDK6MFMK/p1673984401006459#2023-01-1720:47Sam Ritchieodd… I tried to put a println in my macro hook so bb lint would kick out some info (just (prn "cake")` ) and triggered this
[
#2023-01-1720:47Sam Ritchiehttps://github.com/mentat-collective/mafs.cljs/blob/main/bb.edn#L48#2023-01-1720:47Sam Ritchiehere’s my lint task#2023-01-1720:48borkdudetry printing to stderr instead#2023-01-1720:49Sam Ritchielike this?
(binding [*out* *err*]
      (println "cake"))
#2023-01-1720:49Sam Ritchiethat can’t be right since I get
src/mafs/plot.cljs:45:1: error: sci.impl.vars.SciUnbound cannot be cast to java.io.Writer
#2023-01-1720:50Sam Ritchieanyway it works fine if I don’t use the babashka version, but use the cli clj-kondo … for now I will just debug that way#2023-01-1720:51borkdudeFeel free to post an issue about this.#2023-01-1720:51borkdudeOne should be able to print to stderr in hooks :)#2023-01-1720:53Sam Ritchiesg#2023-01-1809:24borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1956#2023-01-1819:42borkdude@U017QJZ9M7W I found a workaround that works with the current clj-kondo:
(def err *err*)

(defn new [{:keys [node]}]
  (binding [*out* err]
    (prn "ERRRRR"))
  (api/reg-finding! (assoc (meta node)
                           :message (str "Interop is no good! " (api/generated-node? (first (:children node))))
                           :type :interop)))
So capture *err* in the top level and then use it at "run time"
#2023-01-1819:42borkdudeI'll fix it the proper way though#2023-01-1813:45Colin P. HillIn a deps project, is there any easy way to get clj-kondo to lint only the source paths? I can just list them manually, but it would be nice to be able to get that info from deps#2023-01-1813:46borkdudeclj-kondo doesn't support this, you have to do it manually#2023-01-1813:47Colin P. HillDang. Okay, thanks. I'll ask in #C6QH853H8, maybe someone has a way to print out the computed :paths.#2023-01-1813:47borkdudeyou can read this from deps.edn, right?#2023-01-1813:48borkdudedo you have such a high churn in source directories that you need to dynamically compute them?#2023-01-1813:49borkdude(this is just a question, I'm not judging you ;))#2023-01-1813:50Colin P. HillIt's more about being able to drop the configuration (or at least this bit of it) into a new project transparently. Also a bit of aesthetics – repeating it feels icky, computing it from a set of aliases feels tidy.#2023-01-1813:50borkdudeyou can do this using a tiny bb script as well#2023-01-1813:51Colin P. HillSure, or jet. Just feels like something someone else would have wanted to do before.#2023-01-1813:52borkdude
clojure -Spath | bb -e '(filter fs/directory? (str/split (slurp *in*) #":"))'
#2023-01-1813:52Colin P. HillAhh, slick, thanks#2023-01-1813:53borkdudeyou may want to tweak it a bit, like this is probably better:
$ clojure -Spath | bb -e '(take-while fs/directory? (str/split (slurp *in*) (re-pattern fs/path-separator)))'
("src" "feature-xml" "feature-yaml" "feature-csv" "feature-transit")
#2023-01-1813:55Colin P. HillAh yeah. I'm on Windows, so that tweak is in fact necessary for me.#2023-01-1813:56borkdudeEven more Windows friendly:
bb -e '(take-while fs/directory? (str/split (with-out-str (babashka.deps/clojure "-Spath")) (re-pattern fs/path-separator)))'
#2023-01-1813:56borkdudeand you could combine this with the clj-kondo pod and combine this all into one script#2023-01-1813:57Colin P. HillNever actually occurred to me to use the pod, I should definitely change my bb task to do that.#2023-01-1817:42Alan BirchenoughI have a noob question related to my indirect use of clj-kondo via Calva. I am using Specter, and it defines handy special values like ALL . Specter docs recommend useing the library, but I don’t like to do that, so I require it :as spctr but also refer some useful values like ALL. However, when I :refer [ALL] I get a warning that says “Unresolved var: ALL”. Also all references to ALL throughout the source file are flagged in the same way. Aside from that, everything is working fine, so clearly the refer behavior found the ALL value and correctly referred it for use in the rest of the file. So how can I avoid these spurious warnings? Thanks for any insight.#2023-01-1817:45borkdudeWhen you include this config: https://github.com/redplanetlabs/specter#clj-kondo and then restart your project, everything will work#2023-01-1817:46Alan BirchenoughOh, good catch. I missed that. Many thanks @U04V15CAJ!#2023-01-1907:36HukkaLooking at the list of linters, I didn't see anything that would warn about missing whitespace in code like (:foo{:foo :bar}). Am I missing something, and would it make sense to have a linter for missing whitespace before all kinds of brackets?#2023-01-1907:48dharriganThere are valid reasons for some code not having a whitespace, i.e., #:foo{:bar :baz}#2023-01-1907:50dharriganI think that whitespace is more a concern of a formatter,, like cljfmt which can insert missing whitespace. Yet, it may be something a linter may consider.#2023-01-2016:57pmooserIs it possible to disable a certain type of warning (`unused-binding`) just inside of destructuring a map ?#2023-01-2016:57pmooserWhen I destructure the incoming arguments of an fn, I often prefer to still give the argument a name using :as but clj-kondo doesn't like it if I don't use that name anywhere.#2023-01-2017:17borkdudeHave you checked linters.md? I believe this is a supported option#2023-01-2017:18borkdude
{:linters {:unused-binding {:exclude-destructured-as true}}}
#2023-01-2017:19pmooser@U04V15CAJ I'm sorry - I looked in config but evidently not closely enough. Thank you!#2023-01-2017:20borkdudeNo worries :)#2023-01-2019:45pavlosmelissinos@U07VBK5CJ I'm pretty sure you can prepend the name with a _ and the linter won't complain. No need to change any options if that works for you. E.g. :as foo -> :as _foo#2023-01-2019:57pavlosmelissinosI omit :as if it's not going to be used in the code so I'd never disable the linter in projects I'm involved but within a team if other people like it _foo tells me two things: what the map represents and that it's not used :slightly_smiling_face:#2023-01-2118:58serioga@U07VBK5CJ I suggest to use :arglists meta for documenting function arguments without performance penalty from unneeded destructuring.#2023-01-2119:17borkdudebut if you're destructuring anyway, then :as x isn't going to add any performance penalty#2023-01-2308:39pmooserI appreciate the feedback too, and I often forget that arglist metadata even exists unless I'm writing macros.#2023-01-2018:51Noah BogartHow interested would you be in a linter that yells about syntax quote on namespaced symbols where the namespace isn't an existing alias? I just dealt with a bug where I was trying to implement the Component library using metadata: (with-meta this {component/start #'start component/stop #'stop}) but I was missing [com.stuartsierra.component :as component] in my :require block, so the functions weren't getting called.#2023-01-2019:12borkdudeI think that would be useful#2023-01-2019:59Noah Bogartcool, I'll write up an issue#2023-01-2020:00borkdude:unresolved-namespace {:syntax-quote true} would maybe make sense#2023-01-2021:41Noah Bogarthttps://github.com/clj-kondo/clj-kondo/pull/1969#2023-01-2020:14borkdude#2023-01-2020:15borkdude@UKFSJSM38 Bump in lsp welcome#2023-01-2020:19borkdudeI see lsp crashes on the newest clj-kondo but this is because it relies on internals (.impl.config)#2023-01-2020:40ericdalloyeah, would be nice to have those usages on public ns I think, I can take a look in the weekend#2023-01-2020:57borkdude#2023-01-2118:45Sam RitchieThis form triggers “redundant-fn-wrapper” on clj-kondo v2022.12.08, and I can’t see why… anyone have a clue?
(let [nsm {}]
     (fn [sym]
       `(.println
         (RT/errPrintWriter)
         ~(nsm sym))))
#2023-01-2119:11borkdudecould be a bug#2023-01-2120:20Noah BogartI wrote that one. Which part of the form is marked as a violation? #2023-01-2120:22borkdudeyou wrote that one? ;) https://github.com/search?q=repo%3Aclj-kondo%2Fclj-kondo+redundant-fn-wrapper&amp;type=commits#2023-01-2120:25borkdudeI think the issue may be that only the code in the unquote is analyzed and the redundant-fn-wrapper isn't aware of the syntax-quote in between#2023-01-2120:25borkdudeso then you're left with:
(let [nsm {}]
  (fn [sym]
    (nsm sym)))
#2023-01-2120:25borkdudewhich makes sense, but not with a syntax-quote in the middle#2023-01-2120:26Noah BogartOops, you’re right, I merely extended it to keywords.#2023-01-2120:27borkdude@UEENNMX0T If you want to provide a PR to fix the issue, more than welcome ;)#2023-01-2120:27borkdudeand an issue to track this .. issue#2023-01-2120:30Noah BogartI’m not at a computer to write the issue but i can take a crack at the fix on Monday#2023-01-2120:32borkdude@U017QJZ9M7W Could you post an issue about this?#2023-01-2120:41Sam Ritchieyes, will do!#2023-01-2120:45Sam Ritchiehttps://github.com/clj-kondo/clj-kondo/issues/1971#2023-01-2120:48Sam Ritchieone more Q for you… I found the following in test.chuck:
(defn ^:private scalb
  [x exp]
  #?(:clj  (Math/scalb ^double x ^int exp)
     :cljs (* x (.pow js/Math 2 exp))))
but the linter reports
src/com/gfredericks/test/chuck/generators.cljc:228:25: error: Unresolved symbol: double
because of this at the top:
(:refer-clojure :exclude [double])
is that correct? should the hint be
(defn ^:private scalb
  [x exp]
  #?(:clj  (Math/scalb ^clojure.core/double x ^int exp)
     :cljs (* x (.pow js/Math 2 exp))))
I had thought that those primitive type hints did NOT have to do with the function names in clojure.core.
#2023-01-2120:52borkdudeyeah, but I think the type hint might have always worked because clj-kondo analyzed it as a reference to the var ;) so it's a bug, feel free to report#2023-01-2120:52borkdudesimilar for int I think#2023-01-2121:04Sam Ritchiehttps://github.com/clj-kondo/clj-kondo/issues/1972#2023-01-2121:11borkdudeThanks!#2023-01-2308:40pmooserI'm assuming I must have some kind of syntax error, but I had turned off certain warnings in comment blocks, but one of them seems to be back. I have the following (excerpt):
:config-in-comment {:linters {:clojure-lsp/unused-public-var {:level :off}}}
But it does not seem to be working. A separate question is, when using clojure-lsp, and we make a config edit for clj-kondo, do we have to do anything to ensure that the config change has been picked up?
#2023-01-2308:45pmooserSo interestingly, if I run clj-kondo from the command line on the whole project, I don't get those errors emitted ... which suggests that maybe however clojure-lsp is running isn't finding my project's clj-kondo config? Hmmm.#2023-01-2308:49borkdudeThis linter is implemented by clojure-lsp and doesn't work with :config-in-comment at the moment#2023-01-2308:54pmooserOh, ok. I must have been wrong that it was previously working ... thank you!#2023-01-2311:30zakkorWhen I define a malli schema for a function and return an incorrect type in the function, clj-kondo does not complain as it would if I passed in an incorrect param for example. Is this expected?#2023-01-2311:53borkduderepro?#2023-01-2311:54zakkor@U04V15CAJ here is an example (I might be doing something wrong)#2023-01-2311:55zakkorbut returning an int when the function spec says it is supposed to return string seems to cause no issues#2023-01-2311:55zakkor
(defn welcome-string
  {:malli/schema [:=> [:cat :int] :string]}
  [name]
  12)

(welcome-string "asd")
#2023-01-2311:56borkdudeI think it will emit an error when you call welcome-string and use its result as a non-string. The checking between the implementation and the actual spec might currently not be implemented yet#2023-01-2312:00zakkorYup, there is an error if you try to pass the result of the function (string) to inc (which wants a number) for example#2023-01-2312:00zakkorWould be huge if the return expression in the function was also typed according to its spec though!#2023-01-2312:01zakkorI imagine that would prevent lots of usual errors, like accidentally returning a higher-order function instead of a number, etc#2023-01-2312:01zakkorInstead of at the call site#2023-01-2312:02borkdudesure, feel free to post an issue#2023-01-2312:48zakkor@U04V15CAJ posted one here: https://github.com/clj-kondo/clj-kondo/issues/1973 (Sorry if I messed that up 😄)#2023-01-2312:49borkdudeCan you also please post some code in there to fully repro the situation? Preferably a github repo someone can clone. This will save the person who is going to implement this time.#2023-01-2312:50zakkorYeah I can, adding now#2023-01-2313:00zakkorUpdated issue to add repro: https://github.com/zakkor/clj-kondo-schema-return-repro/blob/master/src/clj_kondo_schema_return_repro/core.clj Hope that helps#2023-01-2313:00borkdudeThis certainly helps, thanks!#2023-01-2321:30Sam Ritchieis there a tool out there that can auto-sort all of my project’s namespaces?#2023-01-2321:30Sam RitchieI am doing a big rename and 63 namespaces are now unsorted 🙂#2023-01-2321:33dpsutton
❯ clojure-lsp clean-ns
[100%] Project analyzed
Checking namespaces...
Cleaned clojure.java.jdbc-test
Cleaned clojure.java.jdbc.spec
Cleaned clojure.java.jdbc.utilities-test
Cleaned clojure.java.jdbc
Cleaned clojure.java.jdbc.datafy
Cleared 5 namespaces

java.jdbc on  master [!?] via ☕ v17.0.1 on ☁️  metabase-query took 5s
❯ pwd
/Users/dan/projects/clojure/java.jdbc
#2023-01-2321:33dpsuttoni had a copy of java.jdbc and ran clojure-lsp clean-ns on it#2023-01-2321:33dpsutton#2023-01-2321:43Sam Ritchiethat is great#2023-01-2321:57borkdude@U017QJZ9M7W You're not using clojure-lsp yet?#2023-01-2322:13Sam RitchieNot yet! Stuck in my old cider and kondo setup #2023-01-2322:13Sam RitchieSounds like I need to make an upgrade #2023-01-2400:18ericdalloclojure-lsp has tasks to clean-ns, format code using cljfmt and get diagnostics using kondo, all in a single tool :)#2023-01-2321:32dpsuttonclojure-lsp --help lists: > clean-ns Organize ns form, removing unused requires/refers/imports and sorting alphabetically.#2023-01-2321:43Sam Ritchieamazing… docs for clojure-lsp also reminded me of cljfmt
clojure -Sdeps '{:deps {cljfmt/cljfmt {:mvn/version "0.9.2"}}}'   -m cljfmt.main fix test
#2023-01-2321:43Sam Ritchiethat got it done!#2023-01-2401:00escherizeI reinstalled emacs, and something is off. The static linting I get seems to be ignoring my project’s .clj-kondo/config.edn file. I have been tracking down a way to pass it into clojure-lsp but I don’t think there’s a way to do that. Maybe it’s flycheck-clj-kondo? What can I use to track this down? I’ve read a bunch of docs, but no leads.#2023-01-2401:20ericdallofirst double check if you are using flyckeck-clj-kondo or flycheck-lsp#2023-01-2401:20ericdalloClojure-lsp uses kondo under the hood which will check your local kondo config file as well#2023-01-2401:20ericdalloThat sounds more like a wrong project-root so you can lsp-clojure-server-info and confirm project root is correct#2023-01-2402:12escherizeGood! the project root is incorrect.#2023-01-2402:13escherize:project-root-uri "file:///Users/me/dv",#2023-01-2402:13escherizeI have a .clj-kondo .lsp dirs in that path ^. Gonna delete them#2023-01-2402:19escherizeHmm, still getting :project-root-uri "file:///Users/me/dv". When I select the project with projectile, then select a clojure file, I see that those dirs are recreated in dv.
LSP :: Connected to [clojure-lsp:82189/starting].
LSP :: clojure-lsp:82189 initialized successfully in folders: (/Users/bcm/dv)
#2023-01-2402:22escherizeas for flycheck-clj-kondo or flycheck-lsp. How do I check? I can say that lsp-ui-flycheck-list shows me the errors (that should be correct).#2023-01-2402:23escherizeI’m using flycheck-lsp.#2023-01-2402:46escherizeI removed all .clj-kondo dirs from ~, ~/a, ~/a/b, ~/a/b/c. (project is in ~/a/b/c/project). no luck.#2023-01-2403:08escherizetried symlinking in my .lsp/.clj-kondo dirs, and editing lsp-clojure-server-command. but not luck.#2023-01-2403:09escherizeHere’s the log:
2023-01-24T03:07:19.640Z  INFO [clojure-lsp.server:601] - [SERVER] Starting server...
2023-01-24T03:07:19.641Z  DEBUG [clojure-lsp.nrepl:21] - nrepl not found, skipping nrepl server start...
2023-01-24T03:07:19.642Z  INFO [clojure-lsp.server:486] - Initializing...
2023-01-24T03:07:19.643Z  INFO [clojure-lsp.startup:122] - Folder /Users/bcm/dv/.clj-kondo not found, creating for necessary clj-kondo analysis...
2023-01-24T03:07:19.643Z  ERROR [clojure-lsp.db:73] - [DB] No cache DB file found
2023-01-24T03:07:19.643Z  INFO [clojure-lsp.db:66] - [DB] Reading transit analysis cache from /Users/bcm/dv/.lsp/.cache/db.transit.json db took 0ms
2023-01-24T03:07:19.649Z  INFO [clojure-lsp.classpath:103] - Finding classpath via `/opt/homebrew/bin/clojure -A:test:dev -Spath`
2023-01-24T03:07:23.974Z  DEBUG [clojure-lsp.classpath:115] - Classpath found, paths:  ["test" "src" "/Users/bcm/.m2/repository/com/github/askonomm/clarktown/2.0.0/clarktown-2.0.0.jar" "/Users/bcm/.m2/repository/org/clojure/clojure/1.11.1/clojure-1.11.1.jar" "/Users/bcm/.m2/repository/org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar" "/Users/bcm/.m2/repository/org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar"]
2023-01-24T03:07:23.975Z  INFO [clojure-lsp.source-paths:85] - [Startup] Using source-paths from classpath: ["/Users/bcm/dv/src" "/Users/bcm/dv/test"]
2023-01-24T03:07:23.975Z  INFO [clojure-lsp.startup:114] - Copying kondo configs from classpath to project if any...
2023-01-24T03:07:23.989Z  WARN [clojure-lsp.kondo:305] - Non-fatal error from clj-kondo: No configs copied.

2023-01-24T03:07:23.989Z  INFO [clojure-lsp.startup:116] - Copied kondo configs, took 14ms secs.
2023-01-24T03:07:23.989Z  INFO [clojure-lsp.startup:86] - Analyzing classpath for project root #object[sun.nio.fs.UnixPath 0x5ef1b182 "/Users/bcm/dv"]
2023-01-24T03:07:23.990Z  INFO [clojure-lsp.kondo:332] - Analyzing 4 paths with clj-kondo
2023-01-24T03:07:24.482Z  WARN [clojure-lsp.kondo:305] - Non-fatal error from clj-kondo: No configs copied.
#2023-01-2403:09escherizefor some reason it keeps picking ~/dv. not sure why 🙂#2023-01-2403:21escherizecopying ~/dv/b/c/project/.clj-kondo into ~/dv/.clj-kondo gets it working. verysweat_g#2023-01-2406:35pithylesstry touch ~/dv/b/c/project/.projectile and deleting all the lsp and kondo caches higher up the tree #2023-01-2406:38pithylessI’ve had issues with projectile and lsp in monorepos where it would focus on the .git root instead of the inner project. I’ve found the empty .projectile as a duct tape solution to telling it where the root is. Note: you need to make sure all other caches will be gone else you may not see the expected result in testing #2023-01-2410:34ericdalloLSP project root is different than projectile one. try lsp-workspace-folders-remove to remove the wrong one, then lsp and choose the correct root when lsp-mode prompts#2023-01-2416:16escherizeI’ll try this now#2023-01-2416:18escherizelsp-workspace-folders-remove fixed it! Thanks @UKFSJSM38 and thanks for helping, @U05476190.#2023-01-2403:07emccueI think this linter is triggering incorrectly :aliased-namespace-var-usage.#2023-01-2403:08emccuegetting it for this usage, which seems wrong
(ns enterprise.routes.status
  (:require [health-check]
            [enterprise.system :as-alias system]
            [next.jdbc :as jdbc]))

(set! *warn-on-reflection* true)

(defn health-checker
  [{::system/keys [db]}]
  (health-check/health-checker
   {:db (fn []
          (jdbc/execute! db ["SELECT 1;"])
          {:healthy true})}))

(defn routes
  [system]
  [""
   (health-check/reitit-route (health-checker system))])
#2023-01-2403:08emccueusing `
clj-kondo/clj-kondo {:mvn/version "2023.01.12"}
#2023-01-2408:16borkdudeProbably fixed in newer version #2023-01-2510:34borkdudeIntroducing clj-kondo-bb: invoke clj-kondo from babashka scripts (or as a babashka one liner)! clj-kondo babashka https://github.com/clj-kondo/clj-kondo-bb#2023-01-2512:07robert-stuttafordhey @U04V15CAJ! will this match the release cadence of the main clj-kondo? could we rely on being able to get the newest version for both bb and jvm at the same time? 😅#2023-01-2512:24borkdudeThat’s the plan but feel free to bug me any time :)#2023-01-2512:41borkdudeI've added it to the checklist here: https://raw.githubusercontent.com/clj-kondo/clj-kondo/master/CHANGELOG.md#2023-01-2513:10robert-stuttafordstupendous, thank you sir#2023-01-2515:39chrisetheridgethank you for this @U04V15CAJ! its helped simplify our kondo CI linting set up 🙂#2023-01-2521:07Noah BogartConundrum: I'm using #malli and I've copied its configs. I'm also using malli's "clj-kondo/emit!" to get updated checks for the function schemas I write. Both of these include :linters {:unresolved-symbol {:exclude [(malli.core/=>)]}}. I'd like to change this to something better, so I've added :lint-as {malli.core/=> clojure.core/def} and :config-in-call {malli.core/=> {:linters {:redefined-var {:level :off}}}} to my base .clj-kondo/config.edn file. However, the (m/=> my-fn [:=> ...]) call still raises a "redefined var" error. Do the library config files get merged in after the project's base config?#2023-01-2521:11Noah BogartI just had the thought that because it's merely merged, I have to use ^:replace in my own config under :linters {:unresolved-symbol {}} . this works but now I lose the library-specific :unresolved-symbol excludes from other libraries. lol Annoying#2023-01-2521:16Noah BogartRemembering about metadata helped me get it, I think. I've changed the config-in-call to use
:config-in-call {malli.core/=> {:linters {:redefined-var {:level :off}
                                           :unresolved-symbol {:exclude ^:replace []}}}}
Not ideal, but it works for these limited contexts
#2023-01-2521:17borkdudeIf you use mx/defn you can do {:lint-as {malli.experimental/defn schema.core/defn}}#2023-01-2521:18Noah BogartYeah, I saw that in the docs. Right now we're sticking with m/=> cuz it works better for some folks' tooling, but I'm hopeful we can use that soon#2023-01-2604:50escherizeCurious to hear more about that, @UEENNMX0T#2023-01-2605:30Noah BogartWhat more do you want to know?#2023-01-2606:47escherizeSorry if that was vague. I’m curious what tooling difficulties your team ran into#2023-01-2613:40Noah BogartNot everyone uses clj-kondo, mostly the intellij users, so I try to limit macros to those that act very close to normal function calls#2023-01-2610:39borkdude#2023-01-2615:09fmnoiseHi everyone, I have a library and I wanna configure clj-kondo on library level so all library consumers will not need to add that configuration into their projects. What I do is ns-level config in library
{:clj-kondo/config '{:lint-as {...}}}
but when this library is used in another project, this config is ignored so I have to copy that into that project config.
#2023-01-2619:08borkdudeHey @U4BEW7F61 - that config only applies to the code being linted there. If you want to export configuration you can do that like this: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2023-01-2619:09borkdudeIf you have a more concrete example of what your project / config looks like, that will help guide you further#2023-01-2620:17fmnoisethanks @U04V15CAJ, documentation you mentioned completely covers my case#2023-01-2618:22Sam Ritchieodd… in https://github.com/mentat-collective/Mafs.cljs, when I run
clj-kondo --lint src
I see
src/mafs/debug.cljs:6:22: warning: Unresolved var:
src/mafs/line.cljs:14:14: warning: Unresolved var:
src/mafs/plot.cljs:16:10: warning: Unresolved var:
linting took 40ms, errors: 0, warnings: 3
but when I run on the specific file:
clj-kondo --lint src/mafs/debug.cljs
I see
linting took 13ms, errors: 0, warnings: 0
#2023-01-2619:09borkdudemaybe a hook issue?#2023-01-2619:13borkdudeyes, it seems so, if I pull the var reference outside of defcomponent it works:
m/Debug

(defcomponent TransformWidget
  (.-TransformWidget m/Debug))
#2023-01-2619:15borkdudeso you likely have to restore some metadata on some node#2023-01-2619:28Sam Ritchieokay, I’ll check it out!#2023-01-2618:27Noah BogartLinter idea: in test/is, if the assertion is a list and the function is = and there are two entries and one of the entries is a data literal, make sure it's in the first position. aka (is (= 4 (+ 2 2)) "this is good") vs (is (= (+ 2 2) 4) "this is bad") . maybe allow customization in the linter to say whether to put the literal first or second?#2023-01-2620:00borkdudeWorth a shot :)#2023-01-2620:41escherizeIt’s probably been brought up a bunch of times. But is there some concept of “fixing” certain linting mistakes? example: we have some discoruaged vars config like:
:discouraged-vars {my.thing/plus {:message "use our.new.thing/plus instead of my.thing/plus"}
...
}
It would be kinda cool to be able to put in, idk. A default value or even a rewrite-clj function/hook that could be run to “solve” certain linter issues. Is there somwehre I can learn more about this imaginary mechanism if it exists, and/or the reasons behind not offering it?
#2023-01-2620:45borkdudeThe fixing can be done by taking the linter output programmatically, taking those locations with you and then write some rewrite-clj code. The same approach is taken in e.g. carve and clojure-lsp#2023-01-2620:48borkdudeAnother small example: https://github.com/babashka/babashka/blob/master/examples/normalize-keywords.clj#2023-01-2621:20escherizeThanks, makes a lot of sense#2023-01-2621:23borkdudeAnd these scripts can be written in babashka and hooked up to your elisp whatever editor functions (or joyride)#2023-01-2621:34escherizethis would make a slick blog post#2023-01-2819:50lilactownI'm trying to write a hook for a macro that acts a lot like try / catch, but instead uses async & fallback. here's my first pass:
(defn async
  [{:keys [node]}]
  (let [body (:children node)
        fallback (last body)
        body (rest (drop-last body))]
    (if (= 'fallback (first (api/sexpr fallback)))
      (doto (with-meta
              (api/list-node
               `(try
                  
however, using it like
(async "foo" "bar" (fallback "loading ..."))
still emits an error src/town/lilac/dom.cljs:231:8: error: Unresolved symbol: fallback
#2023-01-2819:51lilactownthe prn in that hook logs
<list: (try "foo" "bar" (catch js/Promise p__844__auto__ "loading ..."))> 
#2023-01-2820:02borkdudeYou need to return the new node with {:node node}#2023-01-2820:57lilactownack!!! that fixed it. thanks facepalm#2023-01-2821:10borkdudeno problem :)#2023-01-2913:00Clojuri0anThe following code seems to be checked by flycheck incorrectly#2023-01-2913:01Clojuri0an
(ns 
  (:require [mithril :as m]))

(def my-pictures #js {:view (
                      fn [] (m "div" #js {:class "container"}
                               (m "article" (
                                             (m "h1" #js {:role "button"} "my name")
                                             (m "h2" "My Pictures")))))})
#2023-01-2913:13borkdudeHmm, looks like a bug indeed#2023-01-2913:13borkdudeOh I see#2023-01-2913:13borkdudeUse this:
(:require ["mithril" :as m])
#2023-01-2913:14borkdudeJS libraries are indicated with a string lib name#2023-01-2913:14borkdudeThis is merely a convention, but helpful to let clj-kondo know this is a JS library and you can use the namespace name as a function#2023-01-2913:14borkdudeAnd this convention is also enforced by shadow-cljs#2023-01-2913:16Clojuri0anty, I checked and added it. Oddly, it still has the issue. The following with the same structure does not produce the error#2023-01-2913:16Clojuri0an
(def my-pictures #js {:view (fn []
                                (m "div" #js {:class "container"}
                                   (m "article" 
                                      (m "h1" #js {:role "button"} "my name")
                                      (m "h2" "My Pictures"))))}))
#2023-01-2913:17Clojuri0anFigured it out#2023-01-2913:18Clojuri0anThere was an extra paren there#2023-01-2913:18Clojuri0anShould be fixed#2023-01-2913:26borkdude👍#2023-01-2913:01Clojuri0anerror unresolved symbol m at line 12 (m h1)#2023-01-2913:18Clojuri0anSeems to have been a combination of "mithril" needing to be defined in string (js libraries indicated with string lib name) and extra paren. had bracket in wrong part of the namespace as well. not sure how it managed to have been compiling correctly thus far#2023-01-2923:04noogawhy would clj-kondo complain about unresolved symbols on in arg lists? I think it doesn't like my fn and friends#2023-01-2923:06borkdudeyou need to lint your custom fn with :lint-as#2023-01-2923:06nooga...seems like it evaluated (def fn ...) and stopped treating it as your usual fn?
#2023-01-2923:06borkdude
{:lint-as {core/fn clojure.core/fn}}
#2023-01-2923:06noogathx! going to look into this now 👍#2023-01-2923:07borkdudeyou can do that on your ns form:
(ns core
  {:clj-kondo/config '{:lint-as ...}})
#2023-01-2923:26noogaadded .clj-kondo/config.edn with this:
{:lint-as {core/fn clojure.core/fn
           core/defn clojure.core/defn
           core/let clojure.core/let
           core/defmacro clojure.core/defmacro
           core/loop clojure.core/loop
           core/declare clojure.core/declare
           core/defn- clojure.core/defn-
           core/def- clojure.core/def-
           core/when-let clojure.core/when-let
           core/if-let clojure.core/if-let}
 :linters
 {:redefined-var 
  {:level :off}
  :unresolved-symbol
  {:exclude [set-macro! apply* parse-int gt lt]}}}
and it seems like it cured all squiggly lines across my codebase 😂
#2023-01-3013:21bherrmannHowdy. I'm using "let-def" instead of "let" to debug some things. Using emacs/lsp/clj-kondo I get warnings (which I find visually hard to ignore) around my "let-def" ... I tried
$ cat ~/.clj-kondo/config.edn 
{:lint-as {myspace/let-def clojure.core/let } }
but I still get warnings. Does lsp use a different config location??
#2023-01-3013:21borkdudeCan you try without clojure-lsp?
clj-kondo --lint your.clj
#2023-01-3013:22borkdudeoh you have it in your home config? this is not the right location. It should be:
~/.config/clj-kondo/config.edn
#2023-01-3013:26bherrmannHumm.... I wonder if I'm out of date.
$ /home/linuxbrew/.linuxbrew/Cellar/clj-kondo/2022.11.02/bin/clj-kondo --lint migrate/migrate_bt_code.clj 
migrate/migrate_bt_code.clj:45:13: error: Unresolved symbol: cols
migrate/migrate_bt_code.clj:46:9: error: Unresolved symbol: nxt
migrate/migrate_bt_code.clj:47:9: error: Unresolved symbol: authorrity-id-bch
migrate/migrate_bt_code.clj:48:9: error: Unresolved symbol: authority-description-bch
migrate/migrate_bt_code.clj:49:9: error: Unresolved symbol: authority-id
...
those are the let-def bindings
#2023-01-3013:27borkdudecan you make a fully standalone git repo with a repro? then I'll have a look in an hour or so#2023-01-3013:27borkdudealso insert the config in the in .clj-kondo/config.edn in the repo root#2023-01-3013:27bherrmannYes I can.#2023-01-3013:57bherrmannhttps://github.com/bherrmann7/let-def-issue fyi, command line clj-kondo only reports 1 issue - yet emacs now shows 2... joy. but anyway, the single issue is in the repo.#2023-01-3014:16borkdudemove config.edn to .clj-kondo/config.edn#2023-01-3014:16borkdudeand then:
$ clj-kondo --lint m/my_boat.clj
linting took 26ms, errors: 0, warnings: 0
#2023-01-3014:17borkdudein emacs:#2023-01-3014:18borkdudeif you're using clojure-lsp, you might have to restart your session (once you put the config in the right place, I've seen two issues during this conversation!): lsp-workspace-restart#2023-01-3020:58bherrmannHumm.....
$ clojure-lsp --version
clojure-lsp 2022.05.03-12.35.40
clj-kondo 2022.04.26-SNAPSHOT
#2023-01-3020:58bherrmannI think thats my problem.#2023-01-3021:05borkdudeupgrading wouldn't hurt, but after that it should work. let me know if you run into any other stuff#2023-01-3021:11bherrmannTHANKS!#2023-01-3102:56bherrmann
~/let-def-issue$ clojure-lsp --version
clojure-lsp 2023.01.26-11.08.16
clj-kondo 2023.01.20
~/let-def-issue$ emacs m/my_boat.clj
# emacs shows 2 errors in file
~/let-def-issue$ clj-kondo --lint m/my_boat.clj
m/my_boat.clj:10:11: error: Unresolved symbol: puma
linting took 10ms, errors: 1, warnings: 0
~/let-def-issue$ rm -rf .clj-kondo/
~/let-def-issue$ clj-kondo --lint m/my_boat.clj
linting took 10ms, errors: 0, warnings: 0
~/let-def-issue$

seems like emacs/clojure-lsp is not using ~/.clj-kondo/config.edn
#2023-01-3103:09bherrmannfyi: CIDER 1.6.0 (Buenos Aires)#2023-01-3107:50borkdudeAs I said earlier the home config should be in .config/clj-kondo #2023-01-3116:04bherrmannSorry, I somehow missed that I had the config.edn file in the wrong directory. FYI: It seems clj-kondo reads from it though.
$ strace clj-kondo --lint m/my_boat.clj 2>&1 |grep --color config.edn
stat("/home/bob.herrmann/.clj-kondo/config.edn", {st_mode=S_IFREG|0664, st_size=133, ...}) = 0
open("/home/bob.herrmann/.clj-kondo/config.edn", O_RDONLY|O_LARGEFILE) = 4
lstat("/home/bob.herrmann/.clj-kondo/config.edn", {st_mode=S_IFREG|0664, st_size=133, ...}) = 0
but then I if I move the config (as you suggest)
$ strace clj-kondo --lint m/my_boat.clj 2>&1 |grep --color config.edn
stat("/home/bob.herrmann/.config/clj-kondo/config.edn", {st_mode=S_IFREG|0664, st_size=133, ...}) = 0
open("/home/bob.herrmann/.config/clj-kondo/config.edn", O_RDONLY|O_LARGEFILE) = 4
It uses that also. And! emacs/clojure-lsp seemed to like the latter one! (like you said.) Woo Hoo!! THANKS 👍 🔥 👍 🔥
#2023-01-3116:35borkdude@U0502D2GL It reads that file because it's the first .clj-kondo/config.edn it comes across in a parent directory. If you would have that config in $project/.clj-kondo/config it wouldn't have searched higher up.#2023-01-3119:13bherrmannGreat, thanks. It is working great. And I'm very very happy. Seems irrational to be so excited about such a small thing, but man it kicks butt.#2023-01-3021:47Daniel JompheAfter, what, 2 years of using clj-kondo, this is my first non-understood (potentially) false positive. Cheers for such a great, unobtrusive tool!!! With that said, here's what's puzzling me:#2023-01-3021:49borkdudeCan you post a snippet where I can reproduce this locally?#2023-01-3021:51Daniel JompheSure, thanks a lot!!
(defn foo
  ([^clojure.lang.Symbol var-sym]
   var-sym)
  ([^String a-ns
    ^String a-name
    & {:keys [debug?]}]       ; remove both this & keys ...
   (str a-ns a-name debug?))) ;         and `debug?`    ... and error goes away

(foo 'inc)
#2023-01-3021:53borkdudeInteresting, yes, this looks like a bug#2023-01-3021:54Daniel JompheMight have appeared around the time we switched to Clojure 1.11.#2023-01-3021:54borkdudeJust place a #_:clj-kondo/ignore before (foo 'inc) to get rid of it#2023-01-3021:54borkdude(as a workaround, I'll fix it)#2023-01-3021:54Daniel JompheYes, but I use it in many areas 🙂 Thanks a lot Michiel!#2023-01-3022:02borkdudeYou can put this in your config to repair the type inference:
{:linters {:type-mismatch
           {:namespaces
            {dude
             {foo
              {:arities {1 {:args [:symbol]}
                         :varargs {:args [:string :string {:op :rest :spec :any}]}}}}}}}}
#2023-01-3022:04borkdudehttps://github.com/clj-kondo/clj-kondo/issues/1978#2023-01-3022:04Daniel JompheYes, this does it - thanks a lot for the workaround. I'll keep an eye on release notes in the future to know when to remove the workaround. 🙂#2023-01-3022:05Daniel JompheSubscribed to issue and starred the repo, thanks a lot again!!#2023-01-3107:00chrisetheridgethis is unexpected, right? #include … works here, but i get the warning
.clj-kondo/config.edn:38:21: warning: Expected a map, but got: list
#2023-01-3110:53borkdude#include is an undocumented feature and should be considered unsupported#2023-01-3110:59chrisetheridgeah cool, fine with that!#2023-01-3110:59chrisetheridgethank you 🙂#2023-01-3119:39Noah BogartAfter experimenting with a built-in linter for syntax-quote checking in :unresolved-namespaces (https://github.com/clj-kondo/clj-kondo/pull/1969), I was hoping to write this in a hook on with-meta. Sadly, there seems to be no namespace/required data passed to hooks, so I can't perform the check myself. Is this something you could expose to hooks?#2023-01-3121:18borkdudeCan you be more specific about what data?#2023-01-3121:48Noah Bogarti'd like to be able to look at all of the namespaces that are currently aliased or required, and all of the vars that are referred in the current namespace.#2023-01-3121:50borkdudeissue welcome. there is already one function called ns-analysis which may come close to what you want#2023-01-3121:50borkdudecheck the hook docs#2023-01-3121:50Noah Bogartoh I didn't know about that. I'll check it out, thanks#2023-01-3121:50Noah BogartI was expecting the info to live on the passed in object#2023-01-3121:51borkdudens-analysis has a slightly different use case: it reads from the cache of already analyzed files#2023-02-0115:02markbastianHey folks, is there a way to specify a specific linter config in the :config-in-ns block of the kondo config file? I have the following entry:
:config-in-ns
{printable-namespaces
 {:linters
  {:discouraged-var {:level :off}}}}
With the following discouraged vars
:discouraged-var
{clojure.core/println      {:message "Use clojure.tools.logging instead of clojure.core/println"}
 clojure.core/printf       {:message "Use clojure.tools.logging instead of clojure.core/printf"}
 clojure.string/lower-case {:message "Use metabase.util/lower-case-en instead of clojure.string/lower-case"}
 clojure.string/upper-case {:message "Use metabase.util/upper-case-en instead of clojure.string/upper-case"}
 toucan.db/query           {:message "Use mdb.query/query instead of toucan.db/query"}
 toucan.db/reducible-query {:message "Use mdb.query/reducible-query instead of toucan.db/reducible-query"}}
What I want to do is just disable certain of those discouraged vars. Something like this:
:config-in-ns
{printable-namespaces
 {:linters
  {:discouraged-var {clojure.core/println {:level :off}}}}}
I did try the above, but it doesn’t work. Is this possible? If so, how do I do it? Thanks!
#2023-02-0115:04borkdudeWhat happens if you do :message nil instead of :level :off ?#2023-02-0115:04borkdudeor in addition to it#2023-02-0115:06markbastianTried#2023-02-0115:06markbastianAnd still get the warnings on println#2023-02-0115:06borkdudeok, then this linter doesn't work well with config-in-ns yet I think#2023-02-0115:06borkdudefeel free to post an issue. metabase right?#2023-02-0115:06markbastianYep#2023-02-0115:06markbastianWill do, thanks!#2023-02-0115:56markbastianCreated https://github.com/clj-kondo/clj-kondo/issues/1979. Thanks!#2023-02-0115:25dharriganI hope we don't adopt the same with clj-kondo as our namesake as done? 🙂 #2023-02-0115:31Noah Bogartwe only need to worry when clj-kondo starts having children, I guess#2023-02-0115:31dharrigan😄#2023-02-0115:31quollI’m curious, I see clj-kondo used to report errors, but can it be used to update code? Or is that more for Joyride?#2023-02-0115:31Noah Bogartas discussed above: https://clojurians.slack.com/archives/CHY97NXE2/p1674765705972079#2023-02-0115:32Noah BogartI believe at this time any "automatically fix errors" functionality must come from outside clj-kondo#2023-02-0115:32quollThat’s what I was thinking. Thank you#2023-02-0115:33Noah Bogartno problemo. I also wish we had some "auto fix" functionality in clj-kondo, but i understand that it would be a dramatic increase in scope and require rewiring large portions of the app to support it#2023-02-0115:35borkdude@U051N6TTC A lot of what clj-kondo reports can be fixed by clojure-lsp: those two projects are very much integrated#2023-02-0115:36quollI just had this idea around using common functions in other namespaces, and having the code automatically updated. Something like:
(let [lwr (lower-case a-string)]...)
And having the :require block updating to include [clojure.string :as string] and the code I’d just typed updating to:
(let [lwr (string/lower-case a-string)]...)
Or something like that anyway. Clj-kondo definitely feels like the way to identify these things
#2023-02-0115:37borkdude@U051N6TTC take a look at clojure-lsp: it supports a lot of IDE-like features, all based on the analysis done by clj-kondo#2023-02-0115:37borkduderenaming, navigation, etc#2023-02-0115:37quollThank you#2023-02-0115:38borkdudeThe default settings in lsp-mode are a bit too much, but asking in #CPABC1H61 for how to set it up with sane defaults might be good.#2023-02-0115:38borkdudeThere is also eglot, which is slated to become the "official" lsp client in emacs#2023-02-0115:38borkdudewhich is more minimal than lsp-mode#2023-02-0115:39borkdudecc @UKFSJSM38 :)#2023-02-0115:42ericdalloThis tutorial of https://emacs-lsp.github.io/lsp-mode/tutorials/clojure-guide/ may be of help#2023-02-0115:43borkdudeI'm very happy I waited with "fixing stuff" since clojure-lsp was the final puzzle piece which enables that and works in all major editors#2023-02-0115:43borkdude(except IntelliJ, but coming soon...?)#2023-02-0115:43quollheh @UKFSJSM38 this is actually the page I’ve pulled up and was going to work through when I get a little time 🙂#2023-02-0116:10pezFor the record, and since it was brought up: #C03DPCLCV9N is for scripting VS Code. It could probably be used to utilize clj-kondo analysis for fixing lint problems, since it is for general scripting of your editor. But the solution would be VS Code only. (And clojure-lsp covers this base anyway.)#2023-02-0118:12quollYes, I know it’s for VS Code. But everyone loves it so much, that I’m prepared to switch tools to gain the benefits#2023-02-0213:11Daniel JompheDoes clojure-lsp allow us, after being confronted with a lint warning, to "not only fix it in this occurrence, but also for all occurrences in this file" or even "in this project" like IntelliJ's inspections for e.g. Java?#2023-02-0213:24ericdalloonly for clean-ns ATM @U0514DPR7, removing unused requires and imports, sorting etc#2023-02-0213:28Daniel JompheThanks Eric. We're thinking about supporting not only VS Code, but also IntelliJ, if it means that such functionality would be available to our clojure codebase - haven't tried Cursive since 2016, though, to see if it's supported. But heck, at the speed at which all this tooling advances, who knows what VS Code will be able to do before we're ready to try IntelliJ again. (I miss IntelliJ every day I develop...)#2023-02-0213:30ericdalloyou can run that via CLI as well, on CI for example, then you don't need to worry about editors#2023-02-0213:32Daniel JompheHmm, you're right that it would be good for us to start putting our CI to more use!#2023-02-0213:32borkdude> We're thinking about supporting not only VS Code, Who is supporting what?#2023-02-0213:33Daniel JompheSpeaking about my colleagues, who standardized our dev tools to VS Code for the past few years, even though some of us might prefer other IDEs. I'm the tool guy at our shop, who's tasked with helping the team use VS Code at its best, and might provide them with a second IDE config some day, when priorities allow.#2023-02-0122:11markbastianIs there a way to disable linter warnings in the hooks configured with the :hooks -> :analyze-call section of the kondo config.edn file? I’m trying to discourage clojure.core/print in my main code base, but some of the hooks expand with print usage. If I add #_:clj-kondo/ignore to the hooks themselves they don’t appear to be included in the expansion or that stage of analysis. Is there another way to add an ignore as metadata?#2023-02-0122:18borkdudeWhat do you mean by this one? > but some of the hooks expand with print usage.#2023-02-0122:26markbastianHere are a couple examples: • https://github.com/metabase/metabase/blob/master/.clj-kondo/hooks/common.clj#L51https://github.com/metabase/metabase/blob/master/.clj-kondo/macros/metabase/test/util.clj#L4 IIUC, the linter will expand with-temp-env-var-value to that latter link as shown [here](https://github.com/metabase/metabase/blob/master/.clj-kondo/config.edn#L639). I’m trying to discourage print and variants via :discouraged-var but it picks up those items above. I’ve tried adding #_:clj-kondo/ignore as I mentioned in those locations above but that doesn’t seem to work. Basically I want to suppress the warnings from those locations.#2023-02-0122:27borkdudeAh gotcha. You can check if a node is generated with api/generated-node? and if so, you can just ignore it#2023-02-0122:28borkdudeOh, but the #_:clj-kondo/ignore doesn't work on the node that expands into the print, now I get it#2023-02-0122:28borkdudeHmm, can you post an issue about this? I'll check later this week#2023-02-0122:28markbastianWill do! Thanks!#2023-02-0122:29markbastianThat’s why I was hoping maybe there was/could be a metadata option that doesn’t get discarded.#2023-02-0122:30borkduderight#2023-02-0122:30borkdudeif you want to always ignore the generated result, you could also choose to generate something else ;)#2023-02-0122:31markbastianYeah, thinking of that as an option as well. Maybe str.#2023-02-0122:31borkdudeok, I'm going to log off for today, have a nice day#2023-02-0122:31markbastianYou, too. Thanks!#2023-02-0122:33borkdudeOne option is also to introduce a special print function in your code-base like: metabase.utils/production-print which uses clojure.core/print for production usage and you ignore it only there, and all other clojure.core/print usages are forbidden#2023-02-0122:34markbastianGood idea.#2023-02-0123:25markbastianIssue: https://github.com/clj-kondo/clj-kondo/issues/1980 Thanks!#2023-02-0819:46borkdude@U0JUR9FPH Would you mind updating the issue with a full example, preferably something that can be cloned locally?#2023-02-0819:47markbastianYes, thanks for the reminder.#2023-02-0820:07markbastianLMK if https://github.com/clj-kondo/clj-kondo/issues/1980#issuecomment-1423174419 works for you. You should be able to clone that branch and run kondo on the test dir to see the issue.#2023-02-0820:08borkdudeThanks!#2023-02-0216:48Braden ShepherdsonI'm getting odd behavior from the relatively-new :unused-value. I've got a macro used like
(mt/with-temp-env-var-value [not-a-real-binding (name (:some-key defaults))]
  ;; body...
  )
that has [:hooks :macroexpand] rules that turn it into
(defmacro with-temp-env-var-value [bindings & body]
  `(do
     
#2023-02-0216:51Braden Shepherdsonit's flagging the (name (:some-key defaults)) as "unused value". if I replace it with 7, (:some-key defaults), or even (-> defaults :some-key name), it doesn't complain.#2023-02-0216:51Braden Shepherdsonthat last especially makes it feel like a bug in the linter, since that should itself produce identical expanded code to the original.#2023-02-0305:53DrLjótssonIs anyone aware of a clj-kondo hook for Plumatic Schema's defn?
(s/defn stamped-names :- StampedNames
  [names :- [s/Str]]
  (StampedNames. (str (System/currentTimeMillis)) names))
#2023-02-0305:58DrLjótssonNevermind, upgrading to the latest version fixed it for me.#2023-02-0305:58DrLjótssonLatest version of schema that is#2023-02-0309:49borkdudeI'm not sure what the problem was since schema.core/defn is supported by default in clj-kondo#2023-02-0310:52DrLjótssonYou're right. I’m new to clj-kondo... I don't use schema.core/defn itself, but I have my own macro with the same argument syntax. So I thought that I needed to locate the hook for schema.core/defn to apply it to my macro. But then I just tried :lint-as and it worked fine.#2023-02-0310:52borkdudeyes, lint-as works for that purpose#2023-02-0315:56henrikIs there a way to elide warnings from stuff like ["@heroicons/react/24/outline" :refer [XMarkIcon Bars3BottomLeftIcon MagnifyingGlassIcon]] and its usages? Edit: Sorry, Kondo is not complaining, Cursive is. 😅#2023-02-0318:48escherizeNot sure where to write this, but a linter for docstrings would be nice. This might exist, but anyway: docstrings can reference vars, and checking if the vars are defined would add value. example in 🧵#2023-02-0318:49escherize
(ns here)
(def a 3)
(defn return-a "returns [[hare/a]]" [] a)
^ could result in a linter error in the doc string, since the ns is spelled wrong, and there is no hare/a
#2023-02-0410:36Ben SlessDoes kondo's type analysis model alternatives? I checked the source and if I understood it correctly it doesn't. Why: currently malli exports or schemas as any, would be nice to have support for them#2023-02-0410:37borkdudeYes, it does using sets: #{:vector :string}#2023-02-0410:38borkdudebut maybe it's limited at the moment, not sure#2023-02-0411:31Ben Slessd'oh! it's the last cond#2023-02-0512:08orestisDoes kondo support detecting keywords that could be mistyped? Eg. if a namespaced or even plain keyword appears only once in the codebase it might be a typo?#2023-02-0512:11borkdudeIt doesn't do this, but clojure-lsp might be able to do this as it keeps all the keywords of the whole project in memory#2023-02-0512:12orestisThanks!#2023-02-0512:13orestisI produced an interesting bug the other day by doing search-replace from in-line strings to a var. There was a case statement that broke since case doesn’t support dereferencing vars. #2023-02-0512:14borkdudeThis has come up before but it isn't possible to detect if the users intentionally matches the literal symbol or not#2023-02-0512:17borkdudeWhat we could however detect if when the argument is a certain type (string) and nothing in the case matches that type, we could warn#2023-02-0512:20orestisAh right. If this was an optional linter, it could be easily be circumvented by using the quoted form for the (rare?) cases you want to match against a symbol#2023-02-0512:21orestis(assuming clj-kondo can detect quoted symbols?)#2023-02-0512:21borkdudeyes#2023-02-0512:21borkdudeoptional linter can be done for sure#2023-02-0512:22borkdudedoes your case also have a default case? then the type idea would not pan out#2023-02-0512:22orestis
user=> (case 'foo-var foo-var "something" nil) ;; warn on this
"something"
user=> (case 'foo-var 'foo-var "something" nil) ;; but not on this
"something"
#2023-02-0512:24orestisMy personal opinion (without any data to back it) is that using case as-designed (of not dereferencing symbols) is probably not that much used and a confusing bug (for beginners, at least).#2023-02-0512:24borkdudehuh, the second case is also not valid, quoted symbols in case is never what you want#2023-02-0512:24orestisWhy not? It seems to work exactly the same, right?#2023-02-0512:25borkdudeThis is just co-incidental since 'foo-bar expands by the reader into (quote foo-bar) so it would also match the symbol quote:
user=> (case 'quote 'foo-var "something" nil)
"something"
#2023-02-0512:25orestis
user=> (let [a "foo" b "bar"] (case "foo" 'a :a 'b :b))
Syntax error macroexpanding case at (REPL:1:24).
Duplicate case test constant: quote
#2023-02-0512:26orestisTrue#2023-02-0512:26orestiscase is even more confusing than I thought 🙂#2023-02-0512:26borkdudeall you need to know about case is that the constants are not evaluated#2023-02-0512:27borkdudeand that you can list multiple constants in a list#2023-02-0512:27orestisI used to know that, but when I did the refactoring I was scratching my head.#2023-02-0512:27borkdudeI agree that this often confuses people#2023-02-0512:27orestisThat is, I was away from the REPL - if I was writing new code I'd have caught it, but since it was old code that was being refactored, then it slipped under my radar.#2023-02-0512:28orestisCan you detect if a symbol in the case expression is actually a valid var?#2023-02-0512:28orestisor a local, I guess#2023-02-0512:29borkdudeyes, that can be detected#2023-02-0512:30borkdudein clj-kondo's codebase there is actually a case statement which matches against the names of vars as symbol so that would be one counter-example, but agreed that this is probably an exception to the rule. also using class names in case is an often source of confusion#2023-02-0512:31orestisI think in most "day-to-day" codebases that linter could be enabled, and then disabled for very specific instances of case statements (still should be an optional linter, I guess)#2023-02-0512:31borkdudeas an optional linter I wouldn't have a problem with it#2023-02-0512:31orestisI wonder if an optional linter needs to be so accurate as to look into locals or vars, or instead just ban symbols altogether#2023-02-0512:32borkdudeI'd say just ban symbols. It would be good to scan existing codebases for such usages of case. You can do so using grasp: https://github.com/borkdude/grasp#2023-02-0512:35orestisI always mean to use grasp but I alway forget what it's called. You should pack it in babashka 🙂#2023-02-0512:36orestisSo that it could be e.g. invoked by the command line. (Not really suggesting that, I've no idea about it 😄 )#2023-02-0512:37borkdudeI'll try to cook up a case example ;)#2023-02-0512:46borkdudeAccording to grasp here are some counter-examples:
| :line | :column |                                                                                                                                                                                                               :uri |
|-------+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|   176 |      17 |                                                                                jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/middleware/util/instrument.clj |
|    40 |       5 |                                                                                      jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/middleware/enlighten.clj |
|   176 |      20 |                                                                   jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/fipp/v0v6v26/fipp/clojure.cljc |
|   320 |       5 |                                                  jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader/edn.clj |
|   413 |       5 |                                                      jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader.clj |
|   325 |       5 |                                                    jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader/edn.cljs |
|   434 |       5 |                                                        jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader.cljs |
|   257 |       5 |                                                                                                                       jar:file:/Users/borkdude/.m2/repository/nrepl/nrepl/1.0.0/nrepl-1.0.0.jar!/nrepl/bencode.clj |
|   282 |      16 |                                                                                                                       jar:file:/Users/borkdude/.m2/repository/nrepl/nrepl/1.0.0/nrepl-1.0.0.jar!/nrepl/cmdline.clj |
|  1216 |      23 |                                                                                                               jar:file:/Users/borkdude/.m2/repository/org/babashka/sci/0.3.2/sci-0.3.2.jar!/sci/impl/analyzer.cljc |
|  1284 |      31 |                                                                                                               jar:file:/Users/borkdude/.m2/repository/org/babashka/sci/0.3.2/sci-0.3.2.jar!/sci/impl/analyzer.cljc |
|   144 |       3 |                                                                                                                  jar:file:/Users/borkdude/.m2/repository/org/babashka/sci/0.3.2/sci-0.3.2.jar!/sci/impl/utils.cljc |
|   358 |       4 |                                                                                                            jar:file:/Users/borkdude/.m2/repository/org/clojure/clojure/1.11.0/clojure-1.11.0.jar!/clojure/test.clj |
|   176 |       9 |                                                                                                     jar:file:/Users/borkdude/.m2/repository/org/clojure/clojure/1.11.0/clojure-1.11.0.jar!/clojure/core/server.clj |
|    46 |       6 |                                                                        jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/extract_definition.clj |
|    58 |       5 |                                                                        jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/extract_definition.clj |
|    20 |       7 |      jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzer/v1v1v0/clojure/tools/analyzer/passes/collect_closed_overs.clj |
|    50 |       5 |                jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzer/v1v1v0/clojure/tools/analyzer/passes/elide_meta.clj |
|    21 |       6 |          jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzer/v1v1v0/clojure/tools/analyzer/passes/add_binding_atom.clj |
|   809 |       4 |                                  jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzer/v1v1v0/clojure/tools/analyzer.clj |
|   320 |       5 |                                  jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader/edn.clj |
|   413 |       5 |                                      jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader.clj |
|   325 |       5 |                                    jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader/edn.cljs |
|   434 |       5 |                                        jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader.cljs |
|   427 |       4 |                           jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzerjvm/v1v2v2/clojure/tools/analyzer/jvm.clj |
|   151 |       3 |  jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzerjvm/v1v2v2/clojure/tools/analyzer/passes/jvm/analyze_host_expr.clj |
|    26 |       3 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzerjvm/v1v2v2/clojure/tools/analyzer/passes/jvm/annotate_host_info.clj |
|   327 |       5 |                                                                                          jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/cljs/tools/reader/edn.cljs |
|   436 |       5 |                                                                                              jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/cljs/tools/reader.cljs |
|   415 |       5 |                                                                                            jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/clojure/tools/reader.clj |
|   322 |       5 |                                                                                        jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/clojure/tools/reader/edn.clj |
#2023-02-0512:47orestisAh nice, you're running this against .m2?#2023-02-0512:47borkdudeHere is the first counter-example: https://github.com/clojure-emacs/cider-nrepl/blob/d219ce610d9030108c273fab933538fb3b24d8be/src/cider/nrepl/middleware/util/instrument.clj#L176 You can go through the rest to learn more :) I've just matched against (System/getProperty "java.class.path")#2023-02-0512:48borkdudeI'll push the grasp code#2023-02-0512:48borkdudehttps://github.com/borkdude/grasp/blob/master/examples/case_symbols.clj#2023-02-0512:50orestisThanks, I'll run it against our codebase to see#2023-02-0512:51borkdudeI found one case (!) where it matches the default case as a symbol which it shouldn't, let me fix that#2023-02-0512:53borkdudePushed, less cases now:
| :line | :column |                                                                                                                                                                                     :uri |
|-------+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|   176 |      17 |                                                      jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/middleware/util/instrument.clj |
|    40 |       5 |                                                            jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/middleware/enlighten.clj |
|   320 |       5 |                        jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader/edn.clj |
|   413 |       5 |                            jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader.clj |
|   325 |       5 |                          jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader/edn.cljs |
|   434 |       5 |                              jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader.cljs |
|  1216 |      23 |                                                                                     jar:file:/Users/borkdude/.m2/repository/org/babashka/sci/0.3.2/sci-0.3.2.jar!/sci/impl/analyzer.cljc |
|  1284 |      31 |                                                                                     jar:file:/Users/borkdude/.m2/repository/org/babashka/sci/0.3.2/sci-0.3.2.jar!/sci/impl/analyzer.cljc |
|    46 |       6 |                                              jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/extract_definition.clj |
|    58 |       5 |                                              jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/extract_definition.clj |
|   809 |       4 |        jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzer/v1v1v0/clojure/tools/analyzer.clj |
|   320 |       5 |        jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader/edn.clj |
|   413 |       5 |            jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader.clj |
|   325 |       5 |          jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader/edn.cljs |
|   434 |       5 |              jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader.cljs |
|   427 |       4 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzerjvm/v1v2v2/clojure/tools/analyzer/jvm.clj |
|   327 |       5 |                                                                jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/cljs/tools/reader/edn.cljs |
|   436 |       5 |                                                                    jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/cljs/tools/reader.cljs |
|   415 |       5 |                                                                  jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/clojure/tools/reader.clj |
|   322 |       5 |                                                              jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/clojure/tools/reader/edn.clj |
#2023-02-0512:54borkdudeIt would be good to scan your entire .m2 folder and see if any non-tooling libraries have any examples :)#2023-02-0512:58borkdudehttps://github.com/exoscale/lingo/blob/c731061ca6afa880bab67dcbe812f41f0d4b2953/src/exoscale/lingo.cljc#L381#2023-02-0512:59orestis
| :line | :column |                                                                :uri |
|-------+---------+---------------------------------------------------------------------|
|    59 |      21 | file:/Users/orestis/dev/nosco/nosco-gamma/cljs/nosco/ui/inputs.cljs |
|   176 |      17 |                                                                     |
|    40 |       5 |                                                                     |
|   320 |       5 |                                                                     |
|   413 |       5 |                                                                     |
|   325 |       5 |                                                                     |
|   434 |       5 |                                                                     |
|    32 |       5 |                                                                     |
|  1087 |      22 |                                                                     |
|    58 |       6 |                                                                     |
|  1216 |      23 |                                                                     |
|  1284 |      31 |                                                                     |
|   427 |       4 |                                                                     |
|   327 |       5 |                                                                     |
|   436 |       5 |                                                                     |
|   415 |       5 |                                                                     |
|   322 |       5 |                                                                     |
|   415 |       5 |                                                                     |
|   322 |       5 |                                                                     |
|   809 |       4 |                                                                     |
I see this - the first file is the bug we found (the fix is in a branch) but the rest seems to not have any uris?
#2023-02-0512:59borkdudehttps://github.com/sicmutils/sicmutils/blob/02e7a6edaab345e5c6a516f663ecaeb6507cda26/src/sicmutils/expression/render.cljc#L127#2023-02-0512:59borkdudeoh that's weird, hm#2023-02-0513:00borkdudeDo you have the newest version of carve?#2023-02-0513:00orestisI put 0.0.3 in the deps as per README and copied the example code#2023-02-0513:00borkdudeeh carve, I meant grasp, sorry#2023-02-0513:01borkdudeThe newest version is 0.1.4#2023-02-0513:01orestisI went with the latest master for now#2023-02-0513:01borkdudeI'll update the README#2023-02-0513:05orestishttps://github.com/redplanetlabs/proxy-plus/blob/master/src/com/rpl/proxy_plus.clj#L58 an interesting case#2023-02-0513:07orestishttps://github.com/mikera/core.matrix/blob/develop/src/main/clojure/clojure/core/matrix/impl/ndarray_magic.clj#L102#2023-02-0513:08orestisEverything else is tools.reader, tools.analyzer, clj-kondo plus variations of those vendored in other deps.#2023-02-0513:08borkdudeyeah, so it seems mostly clojure-related / low level libraries that tend to use this#2023-02-0513:09borkdudeor math (sicmutils for examples)#2023-02-0513:09orestisPlus a bug: https://github.com/dm3/clojure.java-time/blob/master/src/java_time/format.clj#L32#2023-02-0513:09borkdudeyou mean, a false positive in carve?#2023-02-0513:10orestisthere's no first argument to the case, so the arguments shift around#2023-02-0513:10orestisA bug in the java.time library#2023-02-0513:10borkdudeoh yes, that's funny#2023-02-0513:10borkdudeI guess clj-kondo could warn on the first argument to case being a constant#2023-02-0513:11borkdudeno this is not a bug#2023-02-0513:11borkdudethere's a threading involved#2023-02-0513:12borkdudeoveruse of threading I'd say ;)#2023-02-0513:34orestisclojure-lsp should have a refactoring to change an if to a cond - but in this case it's even a cond->#2023-02-0513:37borkdudeclj-kondo would have detected this since it expands -> and ->> and so on, but grasp is mostly for doing research on the feasibility of features for clj-kondo, SCI etc so it doesn't have to be 100% accurate#2023-02-0513:38orestisAh interesting. So I guess grasp is not meant to be used as e.g. a very custom lint step or for answering definitive questions about a codebase.#2023-02-0513:38borkdudeit can be but it should be used with this caution in mind#2023-02-0513:39borkdudeif you want to have it 100% accurate wrt macros (which are always the problem when it comes to static analysis) you could double-check with tools.analyzer or so.#2023-02-0513:39borkdudeI think grasp could have an option to expand ->, ->> etc as well, but so far I haven't found it worth the effort yet#2023-02-0516:53borkdude#2023-02-0612:13orestisI have a macro that is linted-as def but I don't want it to trigger :clojure-lsp/unused-public-var - and I would like to avoid putting the :clj-kondo/ignore directive on each callsite. Is it possible to skip a particular linter at the macro-level?#2023-02-0612:14orestisThe macro itself is doing some global mutable state stuff so by definition it is always available as a public var - but obviously clj-kondo doesn't know that...#2023-02-0612:15borkdudethe linter is implemented by clojure-lsp (the only one). @UKFSJSM38 might have an idea#2023-02-0612:15orestisWould it be different if it was another linter?#2023-02-0612:16ericdalloYou have multiple options to ignore that, check the https://clojure-lsp.io/settings/#clojure-lspunused-public-varpage: .clj-kondo/config.edn
{:linters {:clojure-lsp/unused-public-var {:exclude #{my-ns/foo
                                                      my-ns/bar
                                                      other-ns
                                                      my-func}
                                           :exclude-regex #{"my-integration-tests.*"}
                                           :exclude-when-defined-by #{my-ns/defflow}
                                           :exclude-when-defined-by-regex #{"my.custom/macro-.*"}}}}
#2023-02-0612:17borkdudeNice!#2023-02-0612:19orestisSo I guess
:clojure-lsp/unused-public-var {:exclude-when-defined-by
                                           #{nosco.views.design-system-utils/defsection}}
#2023-02-0612:20orestisAnd then when I use
(nds/defsection CardsSection ,,,) 
I shouldn't get the warning? Because it seems it's not working.
#2023-02-0612:20borkdude@U7PBP4UVA I think it would be best if you made a github repro since my experience is that even if this takes a few minutes to put together, it saves time discussing these issues#2023-02-0612:21orestisshould it be in LSP or in Kondo?#2023-02-0612:21borkdudejust a github repo to demonstrate the problem#2023-02-0612:21orestisah true#2023-02-0612:30orestishttps://github.com/orestis/unused-var-demo#2023-02-0612:32ericdallo:exclude-when-defined-by won't work since it only works when kondo includes defined-by analysis, and that only happens in hook level and is defined by user#2023-02-0612:35ericdalloYou will have to: • use :exclude as you are aalready using • create a custom clj-kondo hook and add the defined-by • Make clj-kondo return the defined-by as the macro name currently is returning :defined-by clojure.core/def WDYT @U04V15CAJ?#2023-02-0612:35borkdude@UKFSJSM38 maybe you can make a PR showing that idea?#2023-02-0612:36orestisI'm tinkering with the custom hook, hold on#2023-02-0612:37ericdalloI can try later @U04V15CAJ#2023-02-0612:38borkdudeif you are making a hook you could also emit a usage to suppress the unused public var usage#2023-02-0612:39orestisI was trying a macroexpand first#2023-02-0612:39borkdudesame idea#2023-02-0612:39borkdude
(do (def x ...) x)
#2023-02-0612:44orestisSeems to do the trick https://github.com/orestis/unused-var-demo/commit/db8fe1b33c86ec83f51ba35be3bba896b8964381#2023-02-0612:44orestisBTW @U04V15CAJ the docs for macroexpand use the wording "recommended" to use the same namespaces/files for the macros, but perhaps it should be changed to "required" instead?#2023-02-0612:45orestisI wasn't able to make it work until I moved the kondo macro in the same namespace as the original.#2023-02-0613:23borkdudeIt's not required but you should realize how syntax quote expands#2023-02-0617:15orestisAh yeah, that makes sense - but in my case even a simple def wasn't being picked up. I'll try a repro in that same repo.#2023-02-0716:43Braden ShepherdsonMetabase uses potemkin/import-vars in lots of places. I'm porting a bunch of things to CLJC, and Potemkin doesn't support CLJS at all. I've written this macro as an impoverished potemkin/import-vars for functions only that works cross-platform:
(defn- redef [target sym]
  (let [defn-name (or sym (symbol (name target)))]
    `(def ~defn-name (fn [& args#] (apply ~target args#)))))

(defmacro import-fns
  "Imports defns from other namespaces.
  This uses [[import-fn]] to create pass-through local functions that reload nicely.
  `(import-fns [ns1 f1 f2 f3] [ns2 f4 f5])` creates `f1` that calls `ns1/f1`, `f2` that calls `ns1/f2`, etc.
  If you need to rename a function, instead of just the function name, pass `[original new-name]`."
  [& spaces]
  `(do
     
and it works in the code proper, in both CLJ and CLJS. but clj-kondo doesn't grok this, of course. I wrote a :macroexpand helper:
(defmacro import-fns
  "Kondo macro replacement for [[metabase.shared.util.namespaces/import-fns]]."
  [& pairs]
  `(do 
which doesn't seem to work - I still get warnings about unresolved symbols in the macro call, the :required namespace is flagged as unused, and calls of the imported symbols farther down in the file are also unresolved. I know kondo has special magic for Potemkin's import-vars - is there hope for me to handle this at the kondo config level, or do I need equivalent magic built in? (alternatively, is there a CLJC-friendly alternative to potemkin/import-vars?)
#2023-02-0717:43lreadI'm not opposed to the idea of importing vars at load time, but it is not popular in the Clojure community. My take is that it is more trouble than it is worth. I found myself dealing with too many mysteries with tooling related to its usage. That said, when I took over maintaining rewrite-clj, it used an inlined version of import-vars. When I merged in rewrite-cljs, I created an inlined cljs version of import-vars. Ultimately, I abandoned this load-time approach to importing vars and went with code generation instead. No more import-vars mysteries for me!#2023-02-0717:43Braden ShepherdsonI found and read that issue thread, actually.#2023-02-0717:45Braden ShepherdsonI've managed to hack around the issue by (a) expanding my macro above to hand off to potemkin/import-vars in CLJ context and the above code in CLJS context, and (b) doing :lint-as {metabase.shared.util.namespaces/import-fns potemkin/import-vars} in kondo.#2023-02-0717:45Braden Shepherdsonthat's more than a little bit of a hack, but it gets me access to the potemkin magic in kondo, and everything Just Works.#2023-02-0717:46Braden Shepherdson(it also gives the nicer REPL reload behavior of Kondo in CLJ mode. it's not relevant in CLJS REPLs given the separate compilation step)#2023-02-0721:21borkdudeNice, so :lint-as worked for you if I understand correctly#2023-02-0722:11Braden Shepherdsonyes, it seems that it worked nicely, including the special case magic for potemkin.#2023-02-0812:14dharriganAnyone using amazonica (https://github.com/mcohen01/amazonica) and know what clj-kondo should be configured to lint as the various functions it reflectively generates?#2023-02-0812:15borkdudeI think for that lib I would just give up and add the namespace to :unresolved-namespace {:exclude ...#2023-02-0812:16dharrigan👍 🙂#2023-02-0812:19dharrigan:unresolved-var {:exclude [amazonica.aws.s3]} 🙂#2023-02-0812:19borkdudeIf you care, you could also use the mock feature of clojure-lsp#2023-02-0812:20dharriganI'll have a shifty when I get some time 🙂#2023-02-0812:20dharriganbtw: 🎂#2023-02-0812:20borkdudeThank you! :)#2023-02-0812:41pavlosmelissinosFYI, we are using amazonica in some places but we're looking into migrating to cognitect's aws-api. Amazonica is very macro-heavy and that has caused us a bunch of problems unfortunately... (not being able to inspect the source or easily lint it are two of them) Happy birthday Mr borkdude! 🙂#2023-02-0813:14lispycloudsslightly off topic: just fyi, aws api doesnt support SSO logins on local machines and it quite a deal breaker for us, still sticking to amazonica just for that for things that need to local dev/testing#2023-02-0813:15lispycloudshttps://github.com/cognitect-labs/aws-api/issues/182 is open forever with pretty much no interest from them for a fix#2023-02-0813:15borkdudeDoes https://github.com/grzm/awyeah-api have the same problem?#2023-02-0813:17lispycloudswill try it out#2023-02-0813:17borkdude(probably, as it doesn't aspire to have features beyond aws-api, I think)#2023-02-0813:36pavlosmelissinosWe don't need SSO logins for now but that's good to know, thanks. Given that cognitect maintains the library have you asked them here? I'm sure a PR would go a long way too Btw, this is what they say on their page: > The open source repositories collected here are experimental works in progress by Cognitect. We make these projects available in the hope that you find them useful. These projects are provided without support or guarantee of their continued development. The contribution model and license vary per project, please check each repo for details. so they're not really committed to updating the repo#2023-02-0813:37lispyclouds> I'm sure a PR would go a long way too they dont do PRs though. wouldve been happy to fix it. https://github.com/cognitect-labs/aws-api#contributing#2023-02-0813:37lispycloudsthey dont accept any external fixes in that repo in general it seems#2023-02-0813:37borkdudeMy experience is that pinging the maintainers (@U0ENYLGTA) in the respective channels often helps moving issues further#2023-02-0813:40pavlosmelissinos> they dont accept any external fixes in that repo in general it seems Oh, I see, that's too bad... For what it's worth I've upvoted the issue, let's hope it moves more quickly...#2023-02-0813:45dchelimskyGood news! We are interested in a fix and are working on one. We haven't put anything in the ticket yet because we can't commit to a timeline, but we're adding support for sso in general and CodeCatalyst in specific.#2023-02-0813:46lispycloudsawesome! thanks a lot! 🙏:skin-tone-5: really really excited for this! 😄#2023-02-0813:48dchelimskyMe, too! And I appreciate the frustration of these issues sitting around for so long. We seem to have some momentum right now within Nubank, so, while I can't promise anything, I'm optimistic that we'll be addressing issues more regularly now. Stay tuned!#2023-02-0813:49lispycloudsthis is sincerely appreciated! thanks again. love the lib and this would make it perfect!#2023-02-0813:50dchelimskyOh, perfection is a long way off 🙂 But I'm glad to know it's helping you!#2023-02-0813:51borkdudeYou see, pinging helped :)#2023-02-0813:52borkdudeAnd all of that in the clj-kondo channel due to some issues with amazonica linting 😆#2023-02-0813:53pavlosmelissinosBy the way @U0ENYLGTA I have to say I love the design of aws-api. Being able to list the available operations with (aws/ops client) at runtime might be a simple idea but it is mind-blowing and immensely useful. I'm using it all the time.#2023-02-0813:54dchelimskyYou can thank @U06UY677Y for that 🙂#2023-02-0813:54lispycloudsalso inspires the design for https://github.com/lispyclouds/contajners#2023-02-0813:54borkdudedata oriented programming FTW#2023-02-0814:26dharriganI'm not a particular fan of amazonica personally, much perfer the cognitect libraries, but <shrug> gotta work with what I have been given#2023-02-0814:26dharriganGood 'tho, that I can switch off the warnings 🙂#2023-02-0822:11Braden Shepherdsonis there a convenient way to see what kondo is seeing in an expression/file? I'm having issues with :macroexpand and :analyze-call configuration for a macro and getting puzzling lint errors. I'd love a command that would tell Kondo to print its massaged view of the file to stdout, or something similar.#2023-02-0822:12borkdudeYou can use println in those hooks to print the new node before you return it#2023-02-0822:12borkdudeAnd then call clj-kondo from the command line to see the printed result#2023-02-0822:15Braden Shepherdsonah, that works decently well. it's illuminated a few more steps on the way for me.#2023-02-0822:17borkdudeYou can also develop hooks in the REPL, so you can inline def the vars and inspect them#2023-02-0822:17borkdudeSee this section: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#tips-and-tricks#2023-02-0822:17Braden ShepherdsonMetabase is rigged up for that, yeah.#2023-02-0822:18Braden Shepherdsondoes Kondo's macro system transform regex literals #"\s" into (re-pattern "s")? I can't find where that's coming from, but that's the root issue in this case.#2023-02-0822:19borkdudeI think that's behavior from rewrite-clj#2023-02-0822:19borkdudeperhaps it contains a bug, could be#2023-02-0822:21borkdude
$ bb -e '(rewrite-clj.parser/parse-string "#\"\\s\"")'
<regex: #"\s">
$ bb -e '(rewrite-clj.node/sexpr (rewrite-clj.parser/parse-string "#\"\\s\""))'
(re-pattern "\\s")
#2023-02-0822:22borkdudeThis only happens with the :macroexpand hook since that relies on calling sexpr on the input nodes#2023-02-0822:23Braden Shepherdsonit looks like the escaping is being dropped somewhere, yeah.#2023-02-0822:25borkdudeis it?#2023-02-0822:26Braden Shepherdsonby the time it prints out from the :macroexpand, I'm seeing (re-pattern "s")#2023-02-0822:26Braden Shepherdsonbut it does seem like rewrite-clj is doing the right thing, as in your experiment above.#2023-02-0822:29borkdudeclj-kondo has an older version of rewrite-clj that might be behind in this regard. it's available as clj-kondo.impl.rewrite-clj.*#2023-02-0822:29borkdudein the REPL#2023-02-0822:30borkdude
user=> (clj-kondo.impl.rewrite-clj.node/sexpr (clj-kondo.impl.rewrite-clj.parser/parse-string "#\"\\s\""))
(re-pattern "\\s")
#2023-02-0822:31borkdudelooks correct to me (other than that the re-pattern symbol should be fully qualified)#2023-02-0822:32Braden Shepherdsonyeah, it LGTM too. but the input to my :macroexpand macro is already broken.#2023-02-0822:33borkdudeif you can submit a small repro (smaller is better) with a macroexpand hook, I'll take a look later. it's getting late here. The input is already the result of sexpr since the input are regular s-expressions with macroexpand#2023-02-0822:34Braden Shepherdsonsure, I can find a basic repro and file a bug. I need a repro for that format syntax checking bug too. thanks for your help debugging this.#2023-02-0823:27Braden Shepherdsoncurious! those two bugs are related. I was playing around with the format string issue. (format "%s \"%s\"" "foo" "bar") is no problem, but (wrapper (format "%s \"%s\"" "foo" "bar")) (using the same clone of do macro from the gist for the regex bug) gives the error (`Format string expects 1 arguments instead of 2`). so gut instinct is that strings (including the string in (re-pattern "\\s")) are getting unescaped somewhere in the in the rewrite-clj pipeline kondo uses for macros.#2023-02-0912:20Braden Shepherdsonam I reading it right that because this is a Clojure syntax RuntimeError, not a linter error, I can't avoid it with configuration settings? if that is the case, I can sit on the original change for a few days but I'm not sure how long new releases of rewrite-clj and clj-kondo are likely to take.#2023-02-0912:22borkdudeI think this is a bug in rewrite-clj which I submitted a PR for: https://github.com/clj-commons/rewrite-clj/pull/215 But one of the library tests are failing with that change, so I'll also have to dig into this.#2023-02-0912:22borkdudeclj-kondo doesn't depend on a new version of rewrite-clj being released since it has its own internal fork, to which I'll apply the same change once it's confirmed that this bug + fix makes sense#2023-02-0912:26Braden Shepherdsonokay. I think on further investigation I can work around this by making sure no regex literals are found inside :macroexpand macros by putting the regex in a def.#2023-02-0920:32borkdudeSo I pushed a workaround on clj-kondo master after investigating options all day... There's also a pending issue / PR in rewrite-clj proper but I'm still working on that with @UE21H2HHD - the exact details don't really matter in clj-kondo so I was able to do the workaround there for now#2023-02-1019:06Braden Shepherdsoncool, thanks. I've been following the several rewrite-clj PRs.#2023-02-0918:58Noah Bogartis it possible to convert clj-kondo nodes to sexprs?#2023-02-0918:59borkdudeyes: api/sexpr
#2023-02-0918:59Noah Bogartah, thank you#2023-02-1019:14Noah BogartRelated/follow-up: clj-kondo.impl.rewrite-clj.parser/parse-string doesn't seem to parse anonymous functions in a way that notes they're functions:
; eval (current-form): (p/parse-string "#(+ 1 %)")
{:children
 ({:value +, :string-value "+"}
  {:value 1, :string-value "1"}
  {:value %, :string-value "%"})}
is that intentional? is there another method for parsing input that clj-kondo uses? i'm not sure exactly how it determines what's an anonymous function
#2023-02-1019:18borkdudeHow is this different from normal rewrite-clj? What is the background of your question?#2023-02-1019:18borkdudeOf course clj-kondo can parse such functions as it has to analyze those functions#2023-02-1019:19Noah Bogarti'm using clj-kondo's parser directly because i'm writing an s-expression pattern matching library for use with clj-kondo#2023-02-1019:19borkdudeThe node/tag of that expression determines that it is a function#2023-02-1019:20Noah Bogartoh interesting. thanks#2023-02-1122:11Yuanting MaoFor writing hooks: is it possible to get the lexical context of a macro?
(let [config {:a 1}]
  (my-macro :watch [{:keys [a]} config] ...)) ;; rewrites into (let [{:keys [a]} config] ...)
kondo still cannot resolve symbol a, I assume it's because it is not aware of the binding of config an level above
#2023-02-1122:14borkdudeif you expand into (let [{:keys [a]} config] ...) then there should be no problem, but perhaps your expansion isn't quite right?#2023-02-1122:16Yuanting MaoThanks! Now I know I am in the right direction. Lemme double check my expansion#2023-02-1122:20borkdudeIt often helps to print the node before returning it so you can check it on the command line if it looks right#2023-02-1122:35Yuanting MaoLooks like it is expanding into let, very weird...#2023-02-1122:36borkdudeCan I see the code?#2023-02-1122:37Yuanting MaoFor sure, thanks! It's for linting clojureDart. f/widget is the culprit macro
(let [config {:width 50.0}]
    (f/widget
     :watch [{:keys [width]} config]
     (m/Container
      .width width)))
#2023-02-1122:38Yuanting MaoThis is what I get running clj-kondo --lint (printing the nodes)
[clj-kondo] Linting file: src/acme/main.cljd
:inherit ()
(let [{:keys [width]} config] (m/Container .width width)) {:node <list: (let [{:keys [width]} config] (m/Container .width width))>}
src/acme/main.cljd:14:22: error: Unresolved symbol: width
linting took 248ms, errors: 1, warnings: 0
#2023-02-1122:40borkdudeI remember that someone else has also written some hooks for this: https://clojurians.slack.com/archives/CHY97NXE2/p1650903306070559#2023-02-1122:40borkdudecc @UL05W6AEM - perhaps these hooks can be bundled with that flutter wrapper library#2023-02-1122:41borkdudeAh it's already there: https://github.com/Tensegritics/ClojureDart/blob/main/resources/clj-kondo.exports/tensegritics/clojuredart/hooks/flutter.clj#2023-02-1122:41borkdude@U04AFSRJHNF Is that the same library you're referring to?#2023-02-1122:42borkdudeIf so, then you can install those hooks with:
clj-kondo --lint $(clojure -Spath) --dependencies --copy-configs
#2023-02-1122:43Yuanting MaoYeah, it's the same library. However, I think there's still something wrong... Maybe it's the line numbers#2023-02-1122:44Yuanting MaoI was trying to fix this issue:https://github.com/Tensegritics/ClojureDart/issues/191#2023-02-1122:47Yuanting MaoDid the install but still got the error#2023-02-1122:49borkdudecool. Maybe @UL05W6AEM can help out as well. I'm going to sleep now, but I'll have a look later too#2023-02-1122:53Yuanting Maogood night!#2023-02-1211:08DumchI haven't looked into it in about a half year; I'll see if my code is still in use and try to fix it.#2023-02-1212:13DumchOkay, here's the issue I see: There used to be flutter.alpha/widget, and I wrote the clj-kondo hook to support it. It's not working right now for two reasons: 1. It isn't referenced in clj-kondo/config. 2. Even if it will be referenced, it will not properly work because flutter.alpha2/widget is almost 80% diffrent.#2023-02-1217:43DumchI will add new hook to support these changes#2023-02-1218:02Dumchhttps://github.com/Tensegritics/ClojureDart/pull/194#2023-02-1218:03Dumch@U04V15CAJ, can we add support for a :flds destructuring directly in clj-kondo (https://github.com/D00mch/clj-kondo/commit/26b5901b68d5897d9fcd888350913da8b8c2e9c2)?#2023-02-1218:55borkdude@UL05W6AEM What is :flds?#2023-02-1219:01borkdudeI suppose it's a custom syntax for field destructuring. I know it's tempting, but it's unfortunate that ClojureDart makes up new syntax since this isn't in general good for tooling compatibility. In squint I also have field destructuring but I used metadata to indicate that it's JS destructuring (inspired by the js-interop library):
^:js {:keys [a b c]
This way clj-kondo doesn't have to change for experimental language features. Other tooling that might have problems with this is cursive cc @U2N9GDB1U @U3E46Q1DG
#2023-02-1219:04borkdude@UL05W6AEM thanks for creating that PR to ClojureDart#2023-02-1312:19ingesolIs there a way to declare a minimum version of clj-kondo for a certain config? Right now we are facing issues with using some more recent features, and some of our devs are getting linter errors because their client does not know of those features.#2023-02-1312:23borkdudenot currently, but can be done. issue welcome#2023-02-1312:23borkdudewhat do you expect: should clj-kondo error, or emit a warning, as a lint warning or so? (last seems best to me)#2023-02-1312:26ingesolI guess running with an outdated client should be allowed, blocking that seems pretty intrusive?#2023-02-1312:26ingesolI’ll make an issue #2023-02-1421:03Noah BogartI'm attempting to use clj-kondo as a dependency in a library that i'll compile with GraalVM. It seems that the META-INF files are being picked up by graalvm and used, and it ends up just building a version of clj-kondo on my machine instead compiling my library lol. any suggestions on how to avoid this?#2023-02-1421:49borkdudeMaybe it's because of this? https://github.com/clj-kondo/clj-kondo/blob/master/resources/META-INF/native-image/clj-kondo/clj-kondo/native-image.properties#2023-02-1421:50borkdudeAre you sure it's building clj-kondo, and not just your project but with the name clj-kondo?#2023-02-1421:53Noah Bogartit spit out a clj-kondo bin and when i ran clj-kondo --help it printed the clj-kondo help text lol. looking at your git history, i think i see the changes necessary (moving some of the native-image.properties flags back to my call).#2023-02-1421:53borkdudeok#2023-02-1515:28ingesolI’m seeing some unexpected linter warnings popping up, details and config in thread#2023-02-1515:29ingesol#2023-02-1515:29ingesolLint messages is “Insufficient input”. This seems wrong to me, or is there something I’m not seeing?#2023-02-1515:31ingesolHmmm, also noticing that I might have to report a missing nilable on that tuple to malli#2023-02-1516:16borkdude
[:int :int [:int :int]]
isn't a valid clj-kondo args spec
#2023-02-1516:16ingesolright, thanks. So this is a malli bug#2023-02-1516:18borkdudeI can take a look at why this error appears though, that doesn't look entirely right in clj-kondo either#2023-02-1516:19ingesolwhat would the correct args spec for clj-kondo look like?#2023-02-1516:19borkdudewhat is a tuple in malli, in terms of clojure data structure?#2023-02-1516:20ingesolThis is me speculating, but I think it works on any sequence type. Vectors would make the most sense#2023-02-1516:21borkdudethen [:int :int :nilable/seqable] I think#2023-02-1516:24borkdude
$ clj-kondo --lint - --config '{:linters {:type-mismatch {:namespaces {foo {bar {:arities {3 {:args [:int :int :nilable/seqable]}}}}}}}}' <<< "(require '[foo]) (foo/bar 1 2 3)"
<stdin>:1:31: warning: Expected: seqable collection or nil, received: positive integer.
#2023-02-1619:16Cam SaulQuestion about writing custom hooks: Is there some way to take a symbol/token node and get the fully-qualified version of a symbol that is using a namespace alias? Motivating example: I'm working on a custom linter that will complain if you use certain forms e.g. with-redefs inside parallel tests (we're using a test runner that supports parallel tests). I have it working where it can walk the node and find the symbol with-redefs and error, but it doesn't detect situations if you do something like
(ns my-ns
  (:require [clojure.core :as core]))

(deftest ^:parallel my-test
  (core/with-redefs [...]
    ...))
I would like the hook to be able to take a with-redefs token node or core/with-redefs token node and figure out that in this namespace it's referring to clojure.core/with-redefs . I could figure this out myself if I had access to ns-aliases or something for the namespace being linted
#2023-02-1619:18borkdudeNot currently, but I think we could expose this#2023-02-1619:18borkdudeIssue welcome#2023-02-1619:19Cam Saulok, I'll open one. Thanks!#2023-02-1619:22Cam Saulhttps://github.com/clj-kondo/clj-kondo/issues/1996#2023-02-1713:03borkdudeReleased#2023-02-2011:24TMac@U42REFCKA https://github.com/metabase/metabase/pull/28440#2023-02-1620:41prncHi 👋, with clj-kondo v2023.01.20 I’m seeing unsupported binding form m/scan (`m` is for meander) being classified as an error is there a way to exclude m/scan etc from this check (couldn’t find :unsuported-binding-form linter), or is there some other config parameter I should be looking at? Thanks#2023-02-1620:42borkdude@U7MHWDLD8 Can you provide some more info, e.g. a code snippet in which this occurs?#2023-02-1620:45prncsure thing!#2023-02-1620:47prncThis would be a simple example
(m/search images-data
  (m/scan
   {::url    ?url})
  {:something/uri        (make-uri-entity ?url)})
#2023-02-1620:49prncI don’t think I’ve seen it before but I was on a very old version of clj-kondo 😅#2023-02-1620:50borkdudeAre you using any configuration in .clj-kondo/config.edn for meander?#2023-02-1620:53prnc:face_palm: It was this:
{:lint-as {,,,
           meander.epsilon/match  clojure.core.match/match
           meander.epsilon/search clojure.core.match/match
           ,,,}}
#2023-02-1620:53prncAll is good in the world again, thank you @U04V15CAJ#2023-02-1620:55borkdudeRelease coming tomorrow with a substantial list of new things and improvements: https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#unreleased Please try it out from master, if you're able to. Here is how you can run clojure-lsp + clj-kondo from master: https://github.com/clj-kondo/clj-kondo/issues/1995#issuecomment-1432832765#2023-02-1712:50borkdude#2023-02-1802:58steveb8nPrediction request: will AI be mixed into Kondo? If so, how would it work?#2023-02-1802:58steveb8nJust for the fun of thinking about it#2023-02-1815:03teodorlulsp-propose-refactor? :thinking_face:#2023-02-1820:36steveb8nI could imagine something like "how can I rewrite this fn and what are pros and cons of alternatives"#2023-02-1815:50Sam Ritchiemy first kondo PR… https://github.com/clj-kondo/clj-kondo/pull/1999#2023-02-1815:51borkdudemerged#2023-02-1815:52borkdudeNote that you can also use hooks-api/tag#2023-02-1815:52borkdudea set node will likely have :set or so#2023-02-1815:57Sam Ritchie👍#2023-02-2204:17Matthew TwomeyI’ve noticed when I use in-ns in a file, lsp/kondo looses track of what’s going on. I’m actually not certain if it’s the lsp server or kondo. In this case a picture is worth a thousand words. Notice the color / syntax highlighting of my functions changing as I comment / uncomment the in-ns line. Is there a way I can tweak this so that it still understands properly?#2023-02-2208:21borkdudeAs I said yesterday, clj-kondo doesn’t support this pattern very well and it’s one of the several reasons to avoid it :-) Clj-kondo works best if the ns form contains the information that is necessary for the whole namespace.#2023-02-2212:54borkdudeWhat do the underlines mean btw?#2023-02-2212:54borkdudeMaybe unused public var?#2023-02-2213:04borkdudeIf you can push your code somewhere so I can clone it, I can maybe make some recommendations#2023-02-2216:35Matthew Twomeylol. I knew when I went to bed this would be waiting for me in the morning. I know, you did say it. I just thought I’d check to see if there was a simple setting or something. So two things: 1. The LSP functionality gets wonky even with simple files that use (in-ns. The highlighting gets strange (which is intermittent), but also things like lsp-rename break, and that is consistent. As long as (`(in-ns` is there, I can’t rename functions. Here is a super simple example where that happens:
% find . -type f -exec sh -c "echo '*** {}'; cat {}; echo" \;
*** ./src/foo.clj
(ns foo)

(in-ns 'bar)

(defn fun-1 [] 1)

(defn fun-2 [] (fun-1))

(defn fun-3 [] (fun-2))

*** ./src/bar.clj
(ns bar)

(require 'foo)
2. I think I’m going to just “conform” here and use the more typical pattern where I don’t use (in-ns and if I want to break things up for code-management, I’ll just have to deal with multiple (requires. It’s not that huge a deal and most “things” assume that’s what you’re doing, so I can see now that this will avoid more pain overall. All that said, I really appreciate your help and if you’re simply interested in troubleshooting kondo (in-ns handling - I’m more than happy to keep interacting and testing with you. If not, again - I appreciate you putting up with my questions 🙂
#2023-02-2216:36borkdudelsp depends on clj-kondo's analysis, also the renaming#2023-02-2216:37Matthew Twomeyyeah figured#2023-02-2216:41borkdudeI copied your example, but I wonder what you find unexpected#2023-02-2216:42borkdude> The highlighting gets strange Please be more specific. What message do you see on hover#2023-02-2216:42borkdudeI do see "internal error" with lsp-rename - this may be an error specifically with clojure-lsp. cc @UKFSJSM38#2023-02-2216:43borkdudeI see this in my error log
clojure-lsp.handlers/prepare-rename               handlers.clj:  216
               clojure-lsp.feature.rename/prepare-rename                 rename.clj:  265
                clojure-lsp.feature.rename/rename-status                 rename.clj:  227
                     clojure-lsp.shared/uri->source-path                 shared.clj:  254
                    clojure-lsp.shared/uri->source-paths                 shared.clj:  251
                        clojure-lsp.shared/uri->filename                 shared.clj:  202
                             clojure.string/starts-with?                 string.clj:  365
java.lang.NullPointerException:
#2023-02-2216:45Matthew TwomeySome things like the highlighting strangeness happen after toggling that (in-ns line. With a fresh start of LSP, the highlighting looks ok. However, after a “fresh start” where (in-ns is present, it also detects zero references on everything:#2023-02-2216:45Matthew Twomey(whereas without (in-ns, references are fine)#2023-02-2216:46borkdudeMaybe the file <-> namespace correspondence assumption is also baked into clojure-lsp, I'd not be surprised#2023-02-2216:47Matthew TwomeyYeah, there are a lot of moving pieces. These pieces + my actual emacs config.#2023-02-2216:47ericdalloYeah, that exception is not expected as I don't think we really support in-ns in clojure-lsp as well#2023-02-2216:49Matthew TwomeyOk - np. I’m going to switch away from using in-ns, it’s just too much against the grain of what’s being supported for now. Thanks guys. If you want to revisit down the line and want a guinea pig, I’m your man.#2023-02-2416:01grzmDo people generally exclude imported clj-kondo configs from version control (say, using .gitignore)? We’ve got one (for a transitive dependency that we’re not using) that happens to always trip our cljfmt runs.#2023-02-2416:02borkdudeIf you're not using that library you could just gitignore it. I do check in configs for libs that I am using, so everyone has the same clj-kondo config, but whatever works best for you. does cljfmt support an ignore setting?#2023-02-2416:05grzmI think probably, but I’m currently working out how lsp and cljfmt work together, so I think I’ll just exclude it in deps.edn. That should prevent the clj-kondo config from being imported, correct?#2023-02-2416:06borkdudeyes, I think so#2023-02-2416:06borkdudeas long as it doesn't get into your classpath#2023-02-2416:06grzmYup. At least clj -Stree doesn’t show it 🙂#2023-02-2416:06grzmThanks!#2023-02-2416:07grzmI agree the cljfmt ignore would be more surgical. And maybe I’ll just submit a patch upstream and see if they take it. Thanks!#2023-02-2416:20borkdudegood luck! :)#2023-02-2419:16DerekI’m looking at some legacy code and found the following form (in thread) which kondo does not like. Is it valid Clojure?#2023-02-2419:17Derek
(defprotocol Body
  (to-body [x]))

(extend-protocol Body
  (class (byte-array 0))
  (to-body [this] (RequestBody/fromBytes this)))
#2023-02-2419:17Derekkondo complains that Function arguments should be wrapped in vector.#2023-02-2419:19borkdudeWhich library is this. It is not valid code. See a recent discussion in #CF595DNF7#2023-02-2419:19borkdudeThis code only works by accident#2023-02-2419:19borkdude(https://clojurians.slack.com/archives/CF595DNF7/p1676305329884289)#2023-02-2419:20DerekThanks, it’s internal code unfortunately#2023-02-2419:20borkdudewhy is that unfortunately? then you can change it right?#2023-02-2419:20DerekOh yes! I meant that I could not show you in situ#2023-02-2419:22borkdudeSomething like this should work:
(defprotocol Body
  (to-body [x]))

(extend (class (byte-array 0))
  Body {:to-body (fn [this] (RequestBody/fromBytes this))})
#2023-02-2419:22DerekThank you, I’ll give that a try!#2023-02-2420:58hiredmanIn the above thread @U060FKQPN explains why there are issues with code like, but it is not clear if those issues are a bug in the extend-protocol definition, or if that is invalid code#2023-02-2421:15borkdudeGiven that it only works accidentally for one case, but not when you provide some combination of other stuff (in which clj emits an invalid type hint like ^(class (byte-array 0))) in the expansion) I'd not use it at all at this point, but it would be good if the core team (@U064X3EF3 ?) could shed some light on this if it's supported or a bug.#2023-02-2421:19hiredmanhttps://clojure.atlassian.net/browse/CLJ-1381 appears to be this issue, but not a lot of commentary#2023-02-2421:20borkdudeI personally wouldn't mind if the solution was (extend-protocol Foobar bytes ...)#2023-02-2421:21borkdudebut given that there is extend perhaps we don't need it#2023-02-2520:59geraldodevVery good#2023-02-2712:18CarloI'm writing code using the https://github.com/rm-hull/infix library, for a module with heavy mathematical content. For a simple example, consider:
(infix bpm0 * (1 + percent-bpm-change))
this yields the warning: a number is not a function [not-a-function] . I tried to edit the clj-kondo config.edn like:
{:linters {:not-a-function {:exclude [(infix.macros/infix)]}}}
but I can't get the warning to go away. What am I missing?
#2023-02-2712:20borkdudeCan you try:
:config-in-call {library/infix {:linters {:not-a-function {:level :off}}}}
#2023-02-2712:20borkdudereplace library/infix with the appropriate namespace#2023-02-2712:22CarloYes thank you @U04V15CAJ that immediately fixed the issue! I'll look :config-in-call in the documentation, if you have pointers feel free to share! 🙂#2023-02-2712:23borkdudeThe documentation should have that covered :)#2023-02-2716:53prncHello 👋 I’m seeing clj-kondo v2023.01.20 reporting issues with re-frame layer 3 subscriptions (taking other subs as input) in the presence of :rename . It’s something I’ve not seen in previous versions#2023-02-2716:54prncWhat’s interesting if I just :rename that one thing [reg-sub sub] it seems to be OK with that 😉#2023-02-2716:55borkdudeDoesn't ring a bell. Feel free to provide an issue + repro, preferably something that I can just copy/paste into my editor with the full namespace form#2023-02-2716:55prncSure, will do—thank you!#2023-02-2722:06Noah Bogart#expectations’s expectations.clojure.test/defexpect can do a short-circuit check, where if a name symbol and two forms, wraps the two forms in an (expect) call. So you can write (defexpect some-func-test :ret-val (some-func)) and it will work like a normal (deftest some-func-test (is (= :ret-val (some-func)))). However, if you want to test against a string and you have :lint-as {expectations.clojure.test/defexpect clojure.test/deftest}, then clj-kondo throws a warning/error saying "misplaced docstring", even tho clojure.test/deftest doesn't accept a docstring either. is this worth a github issue or is there a smarter way to lint defexpect calls?#2023-02-2722:07borkdude
:config-in-call {foo/defexpect {:linters {:missing-docstring {:level :off}}}}
is maybe a good workaround
#2023-02-2722:14seancorfield@UEENNMX0T Can you add that as an example to https://github.com/clojure-expectations/clojure-test/issues/29 so I can provide better hooks for that library?#2023-02-2722:19borkdudeI can't really repro your problem @UEENNMX0T
(ns foo
  {:clj-kondo/config '{:linters {:missing-docstring {:level :warning}}
                       :lint-as {foo/deftest clojure.test/deftest}}})

(defmacro deftest "docs" [& _args])
(deftest foo)
I don't see a warning for a missing docstring for foo there
#2023-02-2801:10Noah Bogartminimal reproduction#2023-02-2801:14Noah Bogartone might say it's an unused value, but it's not a docstring:
(meta #'docstring-error)
; {:test #function[noahtheduke.spat-test/fn--24046],
;  :line 373,
;  :column 1,
;  :file "/home/noah/personal/spat/test/noahtheduke/spat_test.clj",
;  :name docstring-error,
;  :ns #namespace[noahtheduke.spat-test]}
#2023-02-2808:45borkdudeAh I see, :misplaced-docstring . Yeah, I think that should never happen in deftest :)#2023-02-2808:45borkdudeIssue welcome#2023-02-2814:58Noah Bogarthttps://github.com/clj-kondo/clj-kondo/issues/2001#2023-02-2814:58borkdudeThanks!#2023-02-2816:00Noah BogartI gave it a go but it relies on analyze-defn and I couldn't figure out how to wrap the body without triggering other linting errors lol (like a do or a let block)#2023-02-2816:01borkdude@UEENNMX0T I think misplaced docstring should only be emitted when the resolved-var is defn, not when it's deftest#2023-02-2816:02Noah Bogartah, so check for :test metadata in analyze-defn?#2023-02-2816:06borkdudeprobably yes#2023-02-2819:11borkdudedefinded-by is probably better since a regular defn may also have test metadata (and I'm not sure if it will be at the name symbol when linting applies)#2023-02-2812:32lassemaattaHow does the output of a clj-kondo analyze-call hook interact with the symbol highlighting in emacs+clojure-lsp?#2023-02-2812:32borkdudedepends what your hook outputs#2023-02-2812:32lassemaattaI'm working on a hook for a macro. I think I got everything correct, and the output of the hook looks fine#2023-02-2812:33lassemaattabut when I move the point in emacs inside some call site of the macro, emacs likes to highlight the whole macro form instead of just the symbol at point#2023-02-2812:33borkdudeah, this is probably a location metadata issue#2023-02-2812:34borkdudeeach incoming node has locations as metadata. when you create new nodes and they don't have locations, they inherit it from the parent node#2023-02-2812:38lassemaattaAh, I see. What I'm working on is a macro (actually several) which are called a bit like this
(defsomething name-of-the-thing
  "an optional docstring"
  {:a-map "with some parameters"
   :options [:and-some :extra-args]}
  [some-arg arguments]
  (foo)
  (bar some-arg)
  (baz extra-arg))
and I'm transforming it into something like
(do
  (defn name-of-the-thing
        "an optional docstring"
        [some-arg arguments and-some extra-args]
        (foo)
        (bar some-arg)
        (baz extra-arg))
  (def name-of-the-thing-options
       {:a-map "with-some-parameters"}))
#2023-02-2812:38borkdudemakes sense#2023-02-2812:39ericdallohttps://github.com/nubank/state-flow/blob/master/resources/clj-kondo.exports/nubank/state-flow/nubank/state_flow.clj#LL34 of a macro we fixed this exact issue, with-meta is important to fix that#2023-02-2812:39borkdudeyou could also put the options on the metadata of the var maybe?#2023-02-2812:39borkdudeI mean in your real code, not clj-kondo#2023-02-2812:40lassemaattayeah, the real macro is quite complex filled with all sorts of nasty magic, the representation above is just what the hook produces which is a simplification of the real thing#2023-02-2812:40lassemaattabut I'll try that with-meta stuff, thanks for the tip#2023-02-2812:41borkdudeyes, or vary-meta to not remove previous metadata#2023-02-2812:43lassemaattais there any documentation regarding this location metadata thing? or is it rather an implementation detail of clj-kondo?#2023-02-2812:43ericdalloGood point, I don't recall having any docs about that detail#2023-02-2812:44borkdudeshould be documented here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#2023-02-2812:45borkdudeIt's not really clear. A PR to clear that up is more than welcome#2023-02-2813:15lassemaattaRight, I think I got my problem fixed, thanks a lot for the help 👍 Btw, is there some "one clever trick" to see how the source node(s) location metadata(s) gets mapped to the output node(s)? I'm testing this in the REPL with api/parse-string so I guess I could perhaps walk the node and merge the metadata with the clj-rewrite nodes under some key and tap> them out to at least see the values..#2023-02-2813:16borkdudenot that I know of#2023-02-2821:16rafaeldelboniHey hello folks, I have the following project structure and I'm trying to call kondo/run! to get the analysis of the file from the right panel, but when I evaluate the (def test-analysis...) my repl gets stuck What I'm doing wrong?#2023-02-2821:18borkdudeDefine "REPL gets stuck". Maybe the output is too large?#2023-02-2821:19rafaeldelboniMy fans go crazy, but it stays there forever.#2023-02-2821:20rafaeldelboniI thought about the output, thats why I declared it into a def to see if was the problem.#2023-02-2821:21dpsuttoni was doing this yesterday. I’m on a recent m1 macbook pro and it takes 25 seconds for me. How long have you waited?
kondo=> (time (do (clj-kondo/run! {:lint ["src"
                                          ;; and your other source paths
                                          ]
                                   :config {:analysis true
                                            :output {:format :edn}}
                                   :config-dir ".clj-kondo"})
                  :done))
"Elapsed time: 25110.974458 msecs"
#2023-02-2821:21rafaeldelbonimaybe a minute, I will wait more hahaha#2023-02-2821:22borkdudetry a lesser amount of code first? ;)#2023-02-2821:22borkdudeoh wait it's only src/test.clj?#2023-02-2821:22rafaeldelboniYes, I was following this doc https://github.com/clj-kondo/clj-kondo/tree/master/analysis#data#2023-02-2821:22dpsuttonalso, i think :lint needs a seqable collection right?#2023-02-2821:22borkdudeyes, it needs to be a vector#2023-02-2821:23rafaeldelboniCOOL#2023-02-2821:23borkdudemaybe a single val is supported, don't remember#2023-02-2821:23rafaeldelboniworked#2023-02-2821:23dpsuttonotherwise it tries to lint “s”, then “r”, “c” … each saying file not found#2023-02-2821:23rafaeldelbonioh wow, ok! Thanks a lot!#2023-02-2821:23dpsutton
:findings [{:filename "c",
             :type :file,
             :col 0,
             :row 0,
             :message "file does not exist",
             :level :error}
            {:filename "r",
             :type :file,
             :col 0,
             :row 0,
             :message "file does not exist",
             :level :error}
            {:filename "s",
             :type :file,
             :col 0,
             :row 0,
             :message "file does not exist",
             :level :error}]
#2023-02-2821:24borkdudestill it's weird that it makes fans spin :)#2023-02-2821:26rafaeldelboniyeah the full path to the file was big: /Users/rafael.delboni/Workspaces/clj/poc-scrapper/src/test.clj#2023-02-2821:26rafaeldelboniif it was trying each char#2023-02-2821:28borkdudeeven then#2023-02-2821:34rafaeldelboniSide note: I just parsed an entire jar, including downloading, unzipping and parsing with only 37 lines of clojure, this is so cool hahaha (sorry)
(ns scratch
  "FIXME: my new org.corfield.new/scratch project."
  (:require [babashka.fs :as fs]
            [clj-kondo.core :as kondo]
            [ :as io]
            [clojure.tools.deps :as deps]))

(defn unpack-jar!
  [local-jar-path target-dir]
  (let [jar-contents-dir (io/file target-dir)]
    (fs/delete-tree jar-contents-dir)
    (fs/unzip local-jar-path jar-contents-dir)
    jar-contents-dir))

(defn get-jar
  [project version]
  (-> (deps/resolve-deps {:deps {project {:mvn/version version}}
                          :mvn/repos {"central" {:url ""},
                                      "clojars" {:url ""}}}
                         nil)
      (get project)
      :paths
      first))

(defn get-jar-files
  [project version]
  (-> (get-jar project version)
      (unpack-jar! (str project "/" version))
      (fs/glob "**{.clj,cljc,cljs}")))

(defn kondo-run!
  [paths]
  (-> {:lint paths
       :config {:output {:format :edn}
                :analysis true}}
      kondo/run!
      :analysis))

(comment
  (let [project 'babashka/fs
        version "0.2.16"]
    (-> (get-jar-files project version)
        kondo-run!)))
#2023-02-2821:37borkdudeYou don't need to unpack the jar, clj-kondo can analyze jar files, so this could become one line#2023-02-2821:38rafaeldelbonidamn!#2023-02-2821:38borkdudewell, except for the tools deps part ;)#2023-02-2821:39rafaeldelboniSo I can do (kondo/run! {:lint [jar-path] ...])?#2023-02-2821:42borkdudeyes#2023-02-2821:42borkdudeyou can pass an entire classpath as well#2023-02-2821:42borkdude[classpath]#2023-02-2821:44rafaeldelbonicool#2023-03-0310:03DrLjótssonIs it possible to configure clj-kondo to ignore all unused functions in one specific namespace?#2023-03-0310:05borkdudeIs this about clojure-lsp/unused-public var?#2023-03-0310:07DrLjótssonI'm not sure. New to Calva... I have a namespace that declares functions that are only called in the REPL. So if possible I would like to disable all warnings like this#2023-03-0310:07borkdudethe docs for those are here: https://clojure-lsp.io/settings/#clojure-lspunused-public-var#2023-03-0310:07DrLjótsson#2023-03-0310:08borkdudethe screenshot shows the linter name: clojure-lsp/unused-public var.#2023-03-0310:09borkdude@UKFSJSM38 would it be an idea to change the default of this linter to opt-in?#2023-03-0310:10DrLjótssonI actually like this linter 🙂#2023-03-0310:10borkdudeah ok, yes, it can certainly be useful :)#2023-03-0310:10DrLjótssonWorked, thanks!#2023-03-0311:11ericdalloI know there are people that prefer to disable, but from my experience it's really useful for most of the people#2023-03-0815:17skylizeI find this linter both useful and annoying. I really wish it could be set in the ns macro, so it could 1. be disabled on-the-fly from namespace I am working on heavily, and 2. leave an easily discoverable record that it is disabled, so if I know not to expect it to work if I open that namespace later.#2023-03-0815:21skylizeI don't know how viable that is. I opened an issue about this a while ago in the Calva repo, thinking it was Calva mishandling things. I think you described some inherent problem with the order things get loaded.#2023-03-0815:35ericdalloit might work but needs some testing, also, from my experience people tend to avoid those config in code but changing on config.edn#2023-03-0815:36borkdudeshouldn't this already work?#2023-03-0815:37ericdalloYeah, not sure if clj-kondo is considering that for custom-lint-fn#2023-03-0815:37skylizeIt works when set from config file, but not when disabled locally from the namespace you want to ignore.#2023-03-0815:37borkdudeok, maybe it can be made to work. I thought clojure-lsp already did something with namespace config#2023-03-0815:41ericdalloThat issue already exists: https://github.com/clojure-lsp/clojure-lsp/issues/1453#2023-03-0815:41ericdalloBorkdude suggested changing the config, not the code#2023-03-0815:55skylizeSo turns out that issue is a dupe of mine. I thought I filed this in Calva, but it was in LSP. https://github.com/clojure-lsp/clojure-lsp/issues/900#2023-03-0815:57skylizeHis suggestion back then was also just to change the config. But I think there is meaningful value in being able to disable this linter locally for the reasons I listed above.#2023-03-0815:57ericdalloWDYT @U04V15CAJ?#2023-03-0816:14borkdudeyes#2023-03-0816:18skylizeThe 2 biggest use-cases I have for disabling unused-public-var are 1. Main API namespace of a library. 2. Namespace I'm working on heavily, where I am adding/deleting things rapidly. For 1, I want to disable it because almost everything is expected be unused. But then I also want that to be self-documented in the namespace. So when I open up the file, I immediately see the linter is off. For 2, I want to quickly add the setting within the file I am working in. Then delete it when I'm mostly done with my work, and let the linter check up on me again. The localized self-documentation is helpful here too, to help me remember to delete it.#2023-03-0816:18borkdudePersonally I don't use unused-public-var at all but just go by the 0 reference count or run carve#2023-03-0816:20borkdudeand yet it's the linter I get the most questions about here 😆#2023-03-0816:20ericdallofor 1: usually will be used if you have tests for that, like clojure-lsp.api for example#2023-03-0816:21ericdalloTBH I think you are the only one I know that relies only on lens for that @U04V15CAJ 😅 , most people find useful that your editor tell that someone forgot a public function which should be: changed to private or just removed#2023-03-0816:21ericdalloI found myself multiple times removing unsued functions because of that#2023-03-0816:22ericdalloI'm totally ok improving the linter, like checking for metas e things like that, and comparing with the past, it improved a lot IMO, I receive way less complains about it nowadays#2023-03-0816:27skylizeYeah. It's definitely helpful... but it's also like "I know! I know! Leave me alone. I'll get to that." Which is when wish I could quickly toss up a temporary config right there where I'm working to get some peace and quiet.#2023-03-0816:27ericdallothat's why it's a info, not warning or error linter#2023-03-0816:27ericdalloLike deprecated#2023-03-0816:30ericdalloI understand your thought, but it looks like a function you are creating and clj-kondo is telling about the unused argument because you didn't use yet :man-shrugging: it's the same thing#2023-03-0816:30skylizeYes. Being an info does help. I am able to choose a more subdued color and have ErrorLens not show the message inline. But there is still noise CV vying for my attention.#2023-03-0816:31ericdalloyeah, I find VScode error lens more verbose than only showing the message when you hover like emacs#2023-03-0816:31skylizeHovering requires mouse input#2023-03-0816:31ericdalloanyway, there is a code action to add a Supress this diagnostics#2023-03-0816:33skylize:thinking_face: By name, that sounds like a viable workaround. What does using that look like?#2023-03-0816:33ericdallo#2023-03-0816:33ericdalloCan't remember right now how to trigger code actions in calva, but it's ctrl + enter or something#2023-03-0816:36skylizeI mean at a high level, how would you use it with what expected result?#2023-03-0816:38ericdallowhen you select that code action clojure-lsp adds that#2023-03-0816:38ericdallofor that specific linter, I'd be happy to include a supress unused at ns level#2023-03-0816:38ericdallobut for that, we need clj-kondo support like mentioned in the issue#2023-03-0816:43skylizeCool shortcut for an inline disable. 😎 Unfortunately brings us right back to the issue at hand. unused-public-var linter cannot currently be disabled locally. Must go in the config file. As is that would be a no-op. 😪#2023-03-0816:44ericdallowhat about a code action to add a config to .clj-kondo/config.edn supressing that namespace ? more work/edn manipulation though but we have rewrite-edn to help#2023-03-0816:57skylizeThat helps only with the convenience factor on the front end. Still not documented in a way you can easily notice it, and still need to go to the config to re-enable.#2023-03-0817:01ericdalloAgreed, maybe we should support it in clj-kondo to make it work just like other linters#2023-03-0817:05skylizeThat would be excellent if you can. 👌#2023-03-0310:27fuadHello! 👋 I'm setting up clj-kondo for a new project and I want to have info-level diagnostics in my editor but not when running the CI check. I could certainly filter the resuts from the output (especially using JSON output + jq), but I'm wondering if there's any cli flags that would allow me to achieve that behavior.#2023-03-0310:29borkdudeyou can set fail-level on the command line to not fail on info level warnings. filtering you can also do using the edn output and a babashka script. I think an issue + PR to filter on a minimum level would be handy#2023-03-0310:29borkdudefor bb + clj-kondo: https://github.com/clj-kondo/clj-kondo-bb#2023-03-0310:43fuad> filter on a minimum level would be handy would report filtering be coupled to fail-level? e.g. something to the effect of
--fail-level error --filter-report (or --report-failures-only)
The alternative would be to have separate levels for fail and report but then it would be possible to have something like
--fail-level warning --report-level error
This would fail on warnings but not report them, which is a bit unintuitive.
#2023-03-0310:45fuadAnother alternative solution to my specific use case would be to always report everything but group by level, so I can easy eyeball what matters.#2023-03-0310:48borkdudeI think the second one would be the most flexible#2023-03-0310:48borkdudewe can have another group-by option, but at that stage you might as well just write a babashka script to make it do what you want#2023-03-0520:19noprompt@borkdude Picking up from #CFFTD7R6Z, my question is this: why should my library, or anyone else’s library for that matter, be expected to maintain configuration for your tool?#2023-03-0520:20nopromptIt seems like an odd design decision if, in fact, I am understanding that is the design.#2023-03-0520:20borkdudeI never said that anyones library should, just that a library can include configuration so everyone using your library gets "correct" linting, navigation, renaming, etc.#2023-03-0520:21nopromptRight, but why does Kondo try to lint something it doesn’t understand?#2023-03-0520:21borkdudekondo doesn't know that it doesn't understand something.#2023-03-0520:22nopromptDoes it know the difference between a macro call and a plain function call? (Edited to make the question positive instead of the negative.)#2023-03-0520:29borkdudeOften clj-kondo knows that it's inside a macro, but it can also function with incomplete knowledge of a project. You can switch off certain things in certain calls (macros, but also functions). Given that projects usually only have a handful of macros, it's often not so tedious to provide configuration as you might think. For meander this may be different, but I haven't even tried. Often macros are very similar to others, you can configure those with {:lint-as {foo/with-foo clojure.core/let} Switching off all warnings in those macros is a bit of a waste if you can easily improve the experience by doing this. I have tried the "disable when inside a macro" approach, but it wasn't that great either, as you can easily get false negatives. Note that providing a config for your macros not only improves lint warnings, but also navigation, renaming, and other IDE-like feature since the analysis that clj-kondo spits out is used by tools like clojure-lsp. clj-kondo also has a :hooks option where you can provide a programmatic transformation of the expression as the user wrote it to another expression that then gets linted/analyzed in turn. This is the most flexible option and should work for all macros. Only as a last resort would I recommend to "disable everything inside this macro".#2023-03-0520:31borkdude> This is the most flexible option and should work for all macros. There is even a :macroexpand option where you can provide an (almost) literal version of your macro as you wrote it in clojure. But meander is a complex beast so I think for meander it would be a less direct and way more simplified version.#2023-03-0520:32borkdudeA relatively simple example for a macro you can see here: https://github.com/borkdude/deflet The exported config is in resources/clj-kondo.exports#2023-03-0520:32nopromptDoes Kondo analyze on a per-file basis?#2023-03-0520:33borkdudeNote that clj-kondo isn't unique here, all static analyzers in clojure have this problem, Cursive users have the same issues and AFAIK clj-kondo is way more flexible in its support for macros#2023-03-0520:33borkdudeyes#2023-03-0520:33borkdudebut it does keep state of other analyzed files on disk around to look up later#2023-03-0520:34nopromptDoes Kondo work inside of a project REPL?#2023-03-0520:35nopromptIOW if I am connected to my project can Kondo lint with respect to that environment?#2023-03-0520:36noprompt99% of the reason I keep going back to Emacs/Cider is because Cider utilizes var meta data.#2023-03-0520:36borkdudeThat question can mean a number of different things, but if you mean: does clojure interact with a Clojure runtime, that runs the project: no. Clj-kondo never executes any of your code. Could it be enriched by looking into a runtime? Yes, possibly, but it doesn't right now. Note that clj-kondo also works for ClojureScript and ClojureDart, without needing to know anything about their runtimes.#2023-03-0520:37nopromptYeah, that’s fine and all. I was asking because it would be nice if it did.#2023-03-0520:37borkdudeclj-kondo also uses var metadata, but statically#2023-03-0520:38nopromptDoes it resolve dependencies?#2023-03-0520:38nopromptBecause I would be fine to do something like
(defmacro do-try-to-lint-this
  {:kondo ,,,}
  ,,,)
#2023-03-0520:39nopromptI used {:style/indent ,,,} all the time like this.#2023-03-0520:42borkdudeclj-kondo itself doesn't resolve dependencies, but you can feed it a classpath:
clj-kondo --lint $(clojure -Spath)
some tools like clojure-lsp do this automatically for you. By feeding it a classpath, it copies exported configs to the local .clj-kondo directory, if you provide more options:
clj-kondo --lint $(clojure -Spath) --dependencies --copy-configs
If you would put in your library:
resources/clj-kondo.exports/meander/epsilon/config.edn
with:
{:linters {:unresolved-symbol {:exclude [(meander.epsilon/match)]}}}
or so, then this would have the same effect. clj-kondo is designed to not have to pollute your code with all kinds of annotations, therefore it's recommended to put it in a config file
#2023-03-0520:44nopromptYeah. I don’t see that as “polluting” however.#2023-03-0520:44borkdudeclj-kondo does support #_:clj-kondo/ignore annotations and namespace metadata configuration, but this isn't "exported" to other users#2023-03-0520:44nopromptI see that as colocating concerns.#2023-03-0520:45nopromptIt kinda reminds me of the splitting of css/html/js and how much more lucid working with React is.#2023-03-0520:45borkdudethe concern of using project local configuration and configuration that you want to export to other users are separate concerns. what goes in your .clj-kondo/config.edn applies to your whole project, but often this contains stuff that you don't want to share with other users.#2023-03-0520:45nopromptRight.#2023-03-0520:47borkdudeI get that you don't want to put any energy in something you don't use yourself. But it's possible for other people to contribute a config for meander here as well: https://github.com/clj-kondo/configs#2023-03-0520:48nopromptSo basically this is a route I could go if I want meander users to not have issues with kondo in their project?#2023-03-0520:48nopromptIf I don’t do that, they have to configure their project.#2023-03-0520:48borkdudeyes#2023-03-0520:49nopromptI’m trying not to feel unhappy about this.#2023-03-0520:49nopromptIt’s a similar unhappy feeling I have with spec.#2023-03-0520:49nopromptThis is supposed to spark joy. 😛#2023-03-0520:50nopromptI don’t think this is a good design.#2023-03-0520:51nopromptAnd I want to be clear that I’m not trying to be critical because I think there’s a lot of good in Kondo but I disagree that these should be the options.#2023-03-0520:52borkdudeWhat kondo does is very similar to other tools. e.g. typescript or graalvm native-image#2023-03-0520:52nopromptClojure is not those languages.#2023-03-0520:52borkdudelibraries can either bundle their types or their types can be made available in another shared repo#2023-03-0520:53nopromptPut another way, those languages do not have macros and so the problem I am specifically bothered by does not exist there.#2023-03-0520:54borkdudethis is true, but the mechanism is similar: providing stuff that enhances the UX or functionality as configuration
#2023-03-0520:54nopromptRight, which brings in my other complaint (and that is not just about Kondo).#2023-03-0520:55borkdude(afk for a bit)#2023-03-0520:55nopromptConfiguration over conventions is really getting old.#2023-03-0520:56nopromptHave you or do you know of anyone that has considered putting together an interface to sanely work the numerous configuration formats out there?#2023-03-0520:57nopromptI know this is OT for this channel, however, Kondo happens to be one of the “last straws” for me in this never ending deluge of Clojure configuration bullshit.#2023-03-0521:01nopromptClojure, unlike JavaScript, has a vanishingly small user base and I think if we’re going to have all these tools that require configuration, it would be nice to have a humane interface for working with them.#2023-03-0521:04nopromptBack on topic, I think because of the nature of macros, Kondo should try to go out of its way to avoid linting ones it is unfamiliar with unless otherwise instructed to do so. I also think I would like the option to “pollute” my var meta data with Kondo configuration so that I do not have to add/commit/maintain a separate file.#2023-03-0521:05nopromptFor my specific annoyances, I would accept the latter as a solution to the former.#2023-03-0521:07nopromptThis is, after all, what meta data is intended for.#2023-03-0521:14borkdudeI'll consider it, thanks for the feedback. Would you mind posting an issue about it, so it can be upvoted by other people? This is how features like this are prioritized.#2023-03-0521:18nopromptYep. Looks like you have a lot of issues though.#2023-03-0521:19mkvlrinteresting ideas here and a good conversation, thank you both#2023-03-0521:20mkvlralso interested in being able to specify this on the var, I’d prefer it to an external file#2023-03-0521:42borkdudeI don't think this will result into not having to check in extra files though, as clj-kondo needs to read some configuration at the moment it encounters a macro call to know what to do with it, so I think the best that can be done is when analyzing that var with exported metadata config, that would get written to a file inside your .clj-kondo directory as an extra part of the configuration. The net benefit of this is marginal#2023-03-0521:43nopromptThat sounds like a design problem. Kondo doesn’t technically need a file to do what it does.#2023-03-0521:46borkdude> Looks like you have a lot of issues though These are mostly feature request#2023-03-0521:46nopromptCider doesn’t need me to maintain files when I put :style/indent on something.#2023-03-0521:46borkdudecider is a server process, clj-kondo is not#2023-03-0521:46nopromptThat’s just an implementation detail.#2023-03-0521:47nopromptEither way, there should be a way for Kondo to cache information like that without requiring an end user to maintain a file.#2023-03-0521:47borkdudeclj-kondo can be run inside a server process, but in general it can be used as a tool that you can just throw code at. for it to know stuff about other namespaces, it goes through an on-disk configuration + cache. It is an implementation detail, but it is how it is.#2023-03-0521:47nopromptYah.#2023-03-0521:48nopromptI mean, since Kondo is writing these files anyway, it seems totally fine for it to write that meta data out too.#2023-03-0521:50borkdudeyou're assuming that clj-kondo will scan your whole project first, that's not how it's designed. you can read about that here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/dev.md#2023-03-0521:51nopromptI guess I’m not understanding the technical constraints that would require me to maintain a file if Kondo has access to the meta data on the var.#2023-03-0521:51nopromptNo, I was assuming what you mentioned previously about being able to hand it a class path.#2023-03-0521:51nopromptObviously on a single file what I’m proposing wouldn’t work if the config was in another file.#2023-03-0521:51borkdudePlease read "design decisions" in dev.md. I hope that will help you understand better what trade-offs were made, even though you might not agree with some of them.#2023-03-0521:53nopromptIf I hand Kondo a class path, it’ll consider the ns dependencies?#2023-03-0521:53nopromptMaybe I misunderstood something.#2023-03-0521:54borkdudeSee design decision number 2 in dev.md, it's about that#2023-03-0521:55nopromptYou mean “Design principles”?#2023-03-0521:55borkdudeyes#2023-03-0521:56nopromptOK. So if I’m reading that correctly it is in agreement with what I’m saying. > The cache directory should only be used to enhance linting, not as a reliance.#2023-03-0521:56borkdudeif you hand clj-kondo a classpath, it wil extract information, like arity info, etc, so you get more feedback, but lint configuration (treat this macro as that macro, etc) should live in .clj-kondo config since you won't rely on having to lint the classpath at all#2023-03-0521:57nopromptTo be clear, I am saying if Kondo is considering a group of files and an ordered analysis, it should be able to utilized any information extracted from those files for the purposes of analysis regardless of ordering.#2023-03-0521:57nopromptBecause this kind of analysis is commutative.#2023-03-0521:58nopromptYou can analyze the files in any order to produce a state of information suitable for any file in that set.#2023-03-0521:58borkdudeif you would analyze all the files in one go, yes. but this is not what's happening when you use clj-kondo via flycheck in emacs for example#2023-03-0521:59nopromptAgain, commutative operation.#2023-03-0521:59nopromptYou can continually update a stream of files, etc. doesn’t matter.#2023-03-0521:59borkdudeyes, that is how it works#2023-03-0521:59nopromptK so I don’t see why I need to maintain a file.#2023-03-0522:00nopromptYou’re basically describing a commutative reduction function over some state value.#2023-03-0522:00borkdudewell, you yourself would maybe not have to maintain a file, but clj-kondo has to persist the extracted information somewhere, right, where do you think that would be, on the moon?#2023-03-0522:00nopromptThat state value could be whatever.#2023-03-0522:00nopromptLOL#2023-03-0522:00nopromptThat’s not my problem.#2023-03-0522:02nopromptYou can put the data wherever you want, why should I have to worry about that? I see some .clj-kondo files added to my project, as a passive user of the tool I shouldn’t have to think about that. K, but if Kondo now creates an issue for people that use my library such that the only remedy I have is to create a file and check that in, I don’t think that is acceptable at all.#2023-03-0522:03nopromptAsking me to put some meta data on my var is a perfectly acceptable solution, however, because that’s in the same space as code I’m maintaining.#2023-03-0522:03borkdudeThat's not your problem at all. People can configure linting for meander they way they like it in their own projects.#2023-03-0522:03nopromptOMFG#2023-03-0522:04borkdudeJust add a part to your README like this: https://github.com/redplanetlabs/specter#clj-kondo and go home.#2023-03-0522:04borkdudeBut if you want to provide a better experience, then you or someone else would have to check in some files with a configuration#2023-03-0522:04borkdudeBut again, you can just tell clj-kondo users to off and invent their own config#2023-03-0522:05nopromptThen I get to be the dick.#2023-03-0522:05nopromptOn a scale of 1 to 10 is what I’m asking difficult?#2023-03-0522:06borkdudeThis is why this exists: https://github.com/clj-kondo/configs Projects that don't want to participate, can ask their users to contribute a configuration over there. It's not on you#2023-03-0522:06nopromptOr does it go against a design proposition or something.#2023-03-0522:06nopromptConsider the situation Kondo is creating by virtue of how it is designed and how those design considerations propagate to everyone else.#2023-03-0522:13nopromptMany Kondo users are passive users. They end up using Kondo because tooling just pulls it in.#2023-03-0522:14borkdudeLibrary authors have the ability to export a shared configuration, but this is not mandatory at all. This was a much requested feature by many people who were happy that it is now possible and many people are using that feature. You can see a list of that here: https://github.com/clj-kondo/clj-kondo/issues/1383 But you can still configure libraries in anyway you like it outside of the scope of that library. If you're not satisfied with clj-kondo, I'm not begging you to use it. Please find a better tool that suits your needs.#2023-03-0522:18nopromptYeah, I get all this. My tl;dr is I want to put config on a var via meta as I think that is easer to maintain for a maintainer. It’s also super easy for me to remember and get in the habit of as I am with :style/indent. It is also more REPL friendly as things can be updated on the fly in the same spot.#2023-03-0522:19nopromptI don’t care about single file shit.#2023-03-0522:19nopromptBecause most people using Clojure, let alone Kondo, are using it on a project basis with a REPL running, etc.#2023-03-0522:21nopromptIf I can then dump that config to disk from a Kondo command or something, I’d probably be open to maintaining that file as part of an automatic pre commit hook.#2023-03-0522:22borkdude> If I can then dump that config to disk from a Kondo command or something, I’d probably be open to maintaining that file as part of an automatic pre commit hook. Now we're talking. I was assuming you didn't want to commit any file at all.#2023-03-0522:32nopromptI don’t want to maintain a file.#2023-03-0522:33nopromptTalking through this, that is ultimately my contention.#2023-03-0522:33nopromptI am fine learning the minimal amount of Kondo configuration for the purposes of being able to stick that on a var and press a button which bakes the file for me.#2023-03-0522:34nopromptBy maintain here I just mean that I don’t want to have to manually update/edit it myself.#2023-03-0522:35nopromptBecause I often write/delete macros etc. I want my editor to respond to those changes without requiring file edits and I want to be able to build those files (since I kinda have to be nice to my users) automatically.#2023-03-0522:37nopromptI can write an issue and even send you a patch or two if you want to collaborate on this.#2023-03-0522:38nopromptNot opposed to that. Again, I think most of what Kondo does out of the box apart from its handling of macros is solid.#2023-03-0522:39borkdudeSure. Please be as detailed as possible in your issue and propose a few concrete things like:
(ns my-namespace.match)

(defmacro my-let
  {:clj-kondo/config '{:lint-as {my-namespace/my-let clojure.core/let}}} 
  [])
The above still feels like too much boilerplate, maybe. But there are many ways to configure the behavior of a macro, this is what probably entails most of the work, finding out good ways to express all the various things you could do, if you didn't want to have it as boilerplatey
(ns my-namespace.match)

(defmacro my-let
  {:clj-kondo/config '{:hooks {:analyze-call {my-namespace/my-let hooks/my-let}}} 
  [])
etc
#2023-03-0522:42borkdudeThe other part of the work is scanning this metadata, then spitting it out to an "extracted config file" which then gets automatically picked up by clj-kondo#2023-03-0522:43borkdudeThis feature request is similar, but it's not the same: https://github.com/clj-kondo/clj-kondo/issues/1927#2023-03-0522:43borkdudeThe request there is to override the config for linting that particular call#2023-03-0522:43nopromptFWIW I use the attr-map? style of meta data all the time, more than ^ and it doesn’t feel like boilerplate.#2023-03-0522:44borkdudeI also used the attr-map? above#2023-03-0522:44nopromptOK. Well, I will jot down an issue. I can link this one too.#2023-03-0522:45nopromptTo be clear, I’d like to work together on this if you’re open to it.#2023-03-0522:45borkdudeyes, sure#2023-03-0522:47nopromptSo that I can experiment with this on my own, when I open that issue (or here is fine too), can you point me in the direction of where I might look to make patches in the code?#2023-03-0522:48nopromptI agree that whatever the solution is, it should be lightweight. The only way to get a feel for it is to try it out.#2023-03-0522:51borkdudeI can give more detailed information when I'm not about to go to bed 😅 like tomorrow. But a few preliminary pointers: There is analyze-defn in impl/analyzer.clj which extracts metadata and keeps this around. This metadata should be searched for "exported" configuration. This exported configuration we should then spit out to .clj-kondo/<org>/<lib>/config.edn (maybe with an extra _extracted suffix on there, to not overwrite other stuff. The two-level directory + config.edn is a convention that is already used by libraries that export config and this gets automatically read and merged with any user config.#2023-03-0522:53borkdudeI think we'd have to use the namespace name + also the .clj(s)(c) extension since there may be multiple files for the same namespace#2023-03-0522:54borkdudemaybe _extracted/<namespace.clj> would be a good two level structure to spit out to#2023-03-0522:54borkdudeso say that you're scanning namespace foo/bar/baz.cljc, you can then spit out the found config to:
.clj-kondo/_extracted/foo.bar.baz.cljc/config.edn
and it would be automatically picked up
#2023-03-0522:55borkdudeand this would then also happen when you're scanning dependencies, so there would be no need for you to check in any files into source control either even#2023-03-0522:56borkdudeI'm off to bed now, thanks#2023-03-0523:04nopromptThanks for the information! I will likely post the issue tomorrow. Also, thanks for hearing me out. I’m glad this discussion turned into an opportunity to try and find a resolution.#2023-03-0615:52lreadfwiw, I am an active user of clj-kondo. I have never been bothered by clj-kondo config files. But this is probably because I am an active user of clj-kondo! I'll follow this issue with interest to learn more about a different perspective and ideas.#2023-03-0617:07imreInteresting discussion indeed, looking forward to checking out the feature request. One thing I had in mind while reading through was macros producing other macros and funky stuff like that. With a bit of work one can support those using config files and hooks, I'm wondering how this approach could deal with those.#2023-03-0617:34mkvlrone downside for me is I use fuzzy search (`projectile-find-file`) to open buffers normally. Having multiple files with the same name makes this worse.#2023-03-0618:43borkdude@U5H74UNSF what "same names" are you referring to specifically?#2023-03-0618:46mkvlreg viewer.cljc and viewer.clj_kondo in clerk. Same name, different extension, makes fuzzy file search slightly more complex.#2023-03-0618:47borkdudeI was just going to say, .clj_kondo is possible to you have a different name.#2023-03-0618:47mkvlrthough I now realize the kondo file name is fully under my control, right?#2023-03-0618:47borkdudeyes.#2023-03-0618:48borkdudebut when using the :macroexpand hook it's often easier to have the same name, so syntax-quotes resolve to the same stuff#2023-03-0618:48borkdudebut not a hard requirement#2023-03-0618:50borkdudewhen you use clojure-lsp, I don't find myself needing projectile-find-file a lot#2023-03-0618:50mkvlrright. Well that weakens my point. Still I value locality and would prefer if I could configure kondo from var metadata I think. Will see when I can play with it.#2023-03-0618:51borkdudeit's an illusion to think that everything can be configured locally, but I want to be open to the experiment#2023-03-0618:53borkdudeI think macros are best served with hook code, which can't be inline-configured anyway, but I think from noprompt's angle, he wants a way to quickly shut up clj-kondo near the macro. I know there are better ways, but someone new to the tool might not want to invest that time (even if it's just once for a macro that will be used for years to come)#2023-03-0618:54borkdudeand macros aren't the only thing to configure#2023-03-0619:05mkvlrwhat prevents hook code from being inlined?#2023-03-0619:07nopromptI think that would mean that the file and its dependencies would need to be loaded.#2023-03-0619:09borkdudetheoretically it's possible to do that, but I think it would become rather messy and error-prone to extract that code into a file that clj-kondo can run, without running into syntax-quote issues, etc#2023-03-0619:09borkdudeit is possible to inline that code as a string, for testing purposes, but it's not really nice to work like that#2023-03-0619:11nopromptYeah, that’s a mixed bag.#2023-03-0619:12nopromptOn the one hand, yes, you could load code and say to users “if you do this be warned I’m going to load your code and that could spell side effects, etc.”#2023-03-0619:13nopromptOn the other you could just not load the code. 😛#2023-03-0619:14borkdude@U06MDAPTP it is often possible to copy a macro almost verbatim and use it with a :macroexpand hook. The reason that clj-kondo doesn't just load this code from source is that in practice, macros can depend on other dependencies, rely on cljs.analyzer , etc. While clj-kondo just wants to have a pure function from s-expr to s-expr or rewrite-clj node to rewrite-clj node. The macro code runs in an interpreter that can't even touch your file system.#2023-03-0619:15nopromptYeah that makes sense.#2023-03-0619:15borkdudeAnother reason is that macro-expansions can often be much simpler for clj-kondo: they don't have to expand into something that works, just something that makes sense to the linter#2023-03-0619:16nopromptRight.#2023-03-0619:16mkvlrwondering if there should also be a setting for the use my macro code as-is for analysis case#2023-03-0619:16borkdudeI have considered that, but I think it would lead to more questions and errors than I can handle ;)#2023-03-0619:17nopromptFor simple rewriting macros that’s probably fine. For macros which are embedded languages that won’t work too well.#2023-03-0619:17borkdudeIt's of course worth an experiment.#2023-03-0619:18mkvlrbut lint-as should be nicely settable using var meta at least, correct?#2023-03-0619:19nopromptThe thing is for something like Meander, in order to provide the analyzer with the most information I would need to write a hook.#2023-03-0619:19nopromptBut I’m not focusing on that case ATM.#2023-03-0619:20borkdude@U5H74UNSF yes, :lint-as and :config-in-call#2023-03-0619:22borkdude
(defmacro my-let
  {:clj-kondo/export {:lint-as clojure.core/let}}
  [...] ...)

(defmacro meatch
  {:clj-kondo/export {:config-in-call {:linters {:unresolved-symbol {:exclude [#"\?.*"]}}}}}
  [...] ...)
or so?
#2023-03-0619:22borkdude(the regex doesn't work for unresolved symbol, but I think it would be nice to be able to suppress ?foo symbols as they are often indicating a local in meander-like macros)#2023-03-0619:24borkdudeI'm not sure if we should just spell out the full config. Maybe that would be less confusing that coming up with a shorter one.
(defmacro my-let
  {:clj-kondo/export {:lint-as {my-ns/my-let clojure.core/let}}}
  [...] ...)
but then there is no need to attach this config to a var at all, you could just float it anywhere in your namespace:
(ns foobar
{:clj-kondo/export {:lint-as {my-ns/my-let clojure.core/let}}})
  
(defmacro my-let
  [...] ...)
#2023-03-0619:25mkvlrin the first case you wouldn’t need to repeat the name if you declare it locally, and you get locality#2023-03-0619:26borkdude@U5H74UNSF what syntax would you propose for lint-as attached to a var?#2023-03-0619:27mkvlr
(defmacro my-let
  {:clj-kondo/lint-as clojure.core/let}
  [...] ...)
#2023-03-0619:27mkvlrmaybe this#2023-03-0619:28borkdudeyeah, maybe. my thought was that we'd need the word export, but if you are the macro author, you "own" it so there's no reason you shouldn't export that config to others#2023-03-0619:30borkdude
(defmacro match
  {:clj-kondo/config {:linters {:unresolved-symbol {:level :off}}}}
  [...] ...)
or
(defmacro match
  {:clj-kondo/disable [:unresolved-symbol]}
  [...] ...)
#2023-03-0619:31borkdude
(defmacro match
  {:clj-kondo/config {:linters {:unresolved-symbol {:exclude [dude]}}}})
  [x]
  (when-not (= 'dude x) x)

(match dude)
#2023-03-0619:32borkdudemakes sense I guess#2023-03-0619:40borkdudehowever it would be kind of confusing since kondo already supports:
(ns foo
  {:clj-kondo/config {:linters ...}})
which is not exported config, but config which only applies to the scope of the namespace.
#2023-03-0619:41borkdudeand we have this feature request which is similar for a call: https://github.com/clj-kondo/clj-kondo/issues/1927#2023-03-0619:48borkdudeWe could also do this. We already have
#_:clj-kondo/ignore (+ 1 2 :three)
We chose "uneval" here (or whatever it may be called) since 1) not every value takes metadata in clojure so you wouldn't be able to put this annotation on numbers, etc otherwise and 2) to not transfer linter instructions/metadata to production code Along the same line we could do:
#_{:clj-kondo/export {:lint-as {my-namespace/with-let clojure.core/let}}} 
#2023-03-0619:50borkdudealthough putting it on the var feels more natural. I just don't want to cause any confusion with stuff that's already there#2023-03-0619:52borkdude
(defmacro my-let
  {:clj-kondo/export {:lint-as clojure.core/let}
  [...] ...)
would mean {:lint-as {my-ns/my-let clojure.core/let}} .Maybe that's the least ambigious and come closest to the other one
#2023-03-0619:54borkdudeand:
(defmacro my-let
  {:clj-kondo/export {:linters {:unresolved-symbol {:exclude [#"^\?"]}}}}
  [...] ...)
#2023-03-0619:54borkdudewould mean {:config-in-call {my-ns/my-let {:linters ...}}}#2023-03-0619:55borkdudethinking-face#2023-03-0619:57borkdudeor maybe:
{:clj-kondo/export {:lint-as {?var clojure.core/let}}}
no different syntax, but you get the fq var symbol interpolated for ?var (inspired by meander 😆 )
#2023-03-0619:58borkdude
{:clj-kondo/export {:config-in-call {?var ...}}}
#2023-03-0620:01borkdude
{:clj-kondo/export {:linters {:discouraged-var {?var {:message "Don't call this function ever again, unless you want to heat up the room via CPU"}}}}}
#2023-03-0620:03borkdudethere are many places in which a var name can occur so supporting a "short" syntax where you can avoid the name of the var is error-prone both for the user and also to interpret that by clj-kondo. The ?var interpolation probably matches better the existing documentation, etc.#2023-03-0620:45borkdudeKind of a prototype:#2023-03-0623:01nopromptFYI I probably won’t get a chance to capture anything on an issue today. I’ve been busy with work today and I gotta take my son to an appointment here in a bit and pretty much be a dad after that for the rest of the day.#2023-03-0623:19borkdudeno problem!#2023-03-1417:50noprompt@borkdude I wanted to let you know that I haven’t forgotten about putting together the issue. Work has been a bit intense the past couple weeks and I’ve been mentally tapped at the end of the day. I still need to get familiar of what would make sense for var configuration but I could see
(defmacro my-macro
  {:clj-kondo/lint-as `case
   :clj-kondo.hooks/analyze-call my-project.hooks/analyze-my-macro}}
  [,,,] ,,,)
and then have kondo expand that to
{:clj-kondo/config
 {:lint-as {my-project/my-macro clojure.core/case}
  :hooks {:analyze-call {my-project/my-macro my-project.hooks/analyze-my-macro}}
Note, this example is only for illustration. The idea is to tweak the configuration so it would make sense for a var.
#2023-03-1418:03nopromptIn terms of getting to “quickly shutting up”, I think having
{:linters {:exclude #{my-project/my-macro}}
or something like this for saying “do not lint this var and ignore all other configuration”.
#2023-03-1418:05nopromptPlacing
{:clj-kondo/exclude true}
on the var meta e.g.
(defmacro ^:clj-kondo/exclude my-macro ,,,)
would thus expand to
{:clj-kondo/config {:linters {:exclude #{my-project/my-macro}}}
etc.
#2023-03-1418:06noprompttrue/`false` corresponds to wether or not the var name should go in the exclusion set.#2023-03-1418:39borkdudeyep, sounds good, looking forward to the issue! there are certain linters that still makes sense in macros, e.g. ones like {:a 1 :b} : missing key for :b, etc.#2023-03-1510:47borkdude@U06MDAPTP https://github.com/clj-kondo/clj-kondo/issues/2010#2023-03-1511:09jeroenvandijkI think what’s described in the issue will help in adopting clj-kondo. I also felt a lot of startup pain with clj-kondo for some projects. It was feeling too overwhelming for me to continue (and I didn’t). Thank you @U06MDAPTP for bringing it up and thank you @borkdude for patiently listening#2023-03-1512:21borkdudeSure! I had another idea for meander-like macros: what if you could say that clj-kondo would take the first unresolved symbol as a binding and the rest of the similar unresolved symbols as binding references? This would make navigation to locals and renaming also work within meander/match etc#2023-03-1512:24borkdude
(defmacro match {:clj-kondo/config {:infer-locals true}}
  [ .. ] ..)
(match {:foo 1 :bar 2} {:foo ?hello (unresolved, treat as local) :bar ?dude (unresolved, treat as local)} [?hello (local ref) ?dude (local ref)])
#2023-03-1520:50borkdudeMaking some progress:#2023-03-1616:17nopromptThat’s looking great! 🙂#2023-03-1620:47borkdudeit's going into the right direction now... hopefully can merge tomorrow after writing some tests..#2023-03-1621:15nopromptMan, that’s great news. Whenever you get it ready I’ll start testing it out!#2023-03-1621:19borkdudeyou can already test it out today, depending on how you want to use it. apart from the tests it's ready I think (apart from some other non-macro stuff I also want to add)#2023-03-1621:20borkdude(and docs)#2023-03-1621:21nopromptI probably won’t get a chance until the weekend because $job. I can probably look at it either Saturday or Sunday.#2023-03-1621:22borkdude👍#2023-03-1711:37borkdudeMerged on master#2023-03-1711:37borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#inline-macro-configuration#2023-03-1711:38mkvlr@borkdude awesome, thank you!#2023-03-1721:06borkdudeclj-kondo new version released#2023-03-0521:14AkizHi, clj-kondo reports ->x as an redefined var. It happens once I create some deftype and then a function prefixed with -> . It is a bug, right?#2023-03-0521:32dpsuttonfrom (doc deftype) > Given (deftype TypeName ...), a factory function called ->TypeName > will be defined, taking positional parameters for the fields#2023-03-0521:32dpsuttonso deftype creates a ->x and then you clobber that when redefining it with defn ->x. The warning is valid and warning you against what you are doing#2023-03-0606:55AkizI’m doing this on purpose, I’m changing the factory in cljdart. Okay, if it’s intentional, I’ll hide it. Thanks for the info.#2023-03-0620:57Sam RitchieTry an alter-var-root instead of a defn #2023-03-0620:59dpsuttonI think that’s a bit much. it’s totally fine to want to do this (or name your function differently since there’s an expectation around ->x. ) . Just suppress the warning.
#_{:clj-kondo/ignore [:redefined-var]}
(defn ->x [])
#2023-03-0609:42andersmurphyHi, is there a way to use specs in :macroexpand hooks? I’m using a spec to conform some macro arguments and it doesn’t seem to work even when using the full name clojure.spec.alpha/def etc.#2023-03-0610:21borkdude@U0JEEGD4N doesn't currently work. I want to wait until spec comes out of alpha in order to not increase binary size and have to support two versions#2023-03-0610:35andersmurphyThat’s fine I can use the messy first draft version of the macro (that doesn’t use spec) for the linting hook. For the most part the macroexpand hook just works which is really nice! Thank you, clj-kondo is awesome.#2023-03-0621:24camdenLet’s say we have the following clj-kondo configuration:
{:lint-as {foo.core/mydefn- clojure.core/defn-}}
clj-kondo will correctly make mydefn- lint as a private function. What I want is the analogous behavior for def:
{:lint-as {foo.core/mydef- clojure.core/def-}} ;; ?! clojure.core/def- doesn't exist: you have to add the ^:private meta tag to a def to get it to be private
Any way to get this behavior?
#2023-03-0621:33borkdudeI'm afraid this doesn't exist. Probably a hook will make this work.#2023-03-0621:33camdenbummer, thanks!#2023-03-0621:34borkdudebut does:
(my-def ^:private foo ...) 
work perhaps?
#2023-03-0621:35borkdudeIt seems so#2023-03-0621:36camdenyeah i want developers consuming this not to have to do that#2023-03-0621:36borkdudeI figured as much#2023-03-0621:36camdenreally appreciate the help though--will share back if i make a hook for this#2023-03-0712:01amithgeorgeFolks, since last week I have had issues with clojure-lsp not working correctly. Reading through the #lsp channel, I found a thread that described my issue (`clj-kondo.lint-as/def-catch-all`). The https://clojurians.slack.com/archives/CPABC1H61/p1677599963893079?thread_ts=1677515210.671249&amp;cid=CPABC1H61 was for the user to fix the clj-kondo lint config. Reading through the clj-kondo docs, I think the macroexpand https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand is what I need to use. My macro in app code
(ns app.test-utils
  (:require [clojure.core.async :as async] ;; the alias is used by other non macro code in this ns
            [app.effects-dispatcher :as effects-dispatcher] 
)

(defmacro with-fx-ch
  [[nom] & body]
  `(let [~nom (clojure.core.async/chan 100)]
     (with-redefs [app.effects-dispatcher/dispatch
                   (fn [[k# v#]] (clojure.core.async/put! ~nom {k# v#}))]
       ~@body)))
The same macro pasted into config at the path ./clj-kondo/app/test_utils.clj
(ns app.test-utils)

(defmacro with-fx-ch
  [[nom] & body]
  `(let [~nom (clojure.core.async/chan 100)]
     (with-redefs [app.effects-dispatcher/dispatch
                   (fn [[k# v#]] (clojure.core.async/put! ~nom {k# v#}))]
       ~@body)))
And the hook in config.edn
{:hooks {:macroexpand {app.test-utils/with-fx-ch app.test-utils/with-fx-ch}}}
This fixes the error with clojure-lsp. However, now clk-kondo is showing the warning "Unresolved namespace clojure.core.async. Are you missing a require?". Why is it complaining about this?
#2023-03-0712:03borkdudeIt's complaining about this because clj-kondo doesn't see a require of the namespace clojure.core.async before the expansion of this macro. You can fix this by providing another bit of config:
{:config-in-call {app.test-utils/with-fx-ch {:linters {:unresolved-namespace {:exclude [clojure.core.async]}}}}
#2023-03-0712:05amithgeorgeIs it unable to see the require in the config macro or the prod macro? the prod macro ns has the require, though the macro itself is using fully qualified fns.#2023-03-0712:06borkdudeIt would have been easier if your macro followed a syntax of an existing macro, so you can use :lint-as. Can you give an example of how this macro is called in practise? It might be similar to cljs.test/async#2023-03-0712:07borkdudeIf you have a namespace like this:
(ns foo (:require [app.test-utils]))
(app.test-utils/with-fx-ch ...)
it will expand into:
(ns foo (:require [app.test-utils]))
(let [.. (clojure.core.async/chan 100)])
#2023-03-0712:07borkdudeand in that namespace, clojure.core.async hasn't been required yet, so clj-kondo complains about it.#2023-03-0712:08borkdudeanother way to suppress this from the macro expansion side is:
(vary-meta ... assoc :clj-kondo/ignore [:unresolved-namespace])
#2023-03-0712:08borkdudebut this will suppress all such problems within the macro usage#2023-03-0712:08amithgeorgeSample usage
(testing "some side effecty code"
  (test-utils/with-fx-ch [effects]
    (testing "scenario X"
      (execute-the-subject)
      (email-sent? effects))))
#2023-03-0712:08borkdudeI'd just add the config#2023-03-0712:09borkdudeit seems you could also use {:lint-as {your.ns/your-macro clojure.core/fn} perhaps#2023-03-0712:12borkdudeSeems to work fine:
(ns app.test-utils
  {:clj-kondo/config '{:lint-as {app.test-utils/with-fx-ch clojure.core/fn}}}
  (:require [clojure.test :refer [testing]]))

(defmacro with-fx-ch
  [[nom] & body]
  `(let [~nom (clojure.core.async/chan 100)]
     (with-redefs [app.effects-dispatcher/dispatch
                   (fn [[k# v#]] (clojure.core.async/put! ~nom {k# v#}))]
       ~@body)))

(testing "some side effecty code"
  (with-fx-ch [effects]
    (testing "scenario X"
      (prn effects))))
#2023-03-0712:17amithgeorgeYeah. I tested it locally and it works!#2023-03-0712:17amithgeorgeI wouldn't have seen that equivalence with fn . Thank you!#2023-03-0712:36BenjaminCan I configure a macro that is like defn but has an optional arg in front of the symbol? defn-foo {:foo :bar} handler defn-foo handler both result in hander being defined. Right now I have :lint-as clojure.core/defn but I think it doesn't handle the second form#2023-03-0712:38borkdudeCan you give the complete form?#2023-03-0712:39borkdudedoes it have problems with the first or the second?#2023-03-0712:45Benjaminproblems with the first form I mean. When I have more args in front.
(defn-handler {:permissions :read-application} retrieve-foo
 [{{:keys [application-id]} :path-params :as req}
  {:foo :foo}])
retrieve-foo does not end up being counted as symbol
#2023-03-0712:45borkdudeyeah, that's not syntax that defn has so it won't work. why not use var metadata instead of a custom macro?#2023-03-0712:46borkdudeor you can support the map after the name in your custom macro, then it would work since that's where normally the metadata goes#2023-03-0712:46borkdude
(defn foo {:hello :there} [])
#2023-03-0712:47BenjaminI guess we were to macro happy in the code base I am working rn#2023-03-0712:49Benjaminits a good lesson, if you make a defn macro, add extra args to where the body usually goes I guess. In the spot that :pre etc goes I suppose#2023-03-0712:51borkdudethe other option, other than writing a hook is to use {:lint-as {your.ns/your-macro clj-kondo.lint-as/def-catch-all}#2023-03-0712:51Benjamin👀#2023-03-0714:22imreDoes the :macroexpand hook support the .clj_kondo extension?#2023-03-0714:22borkdudeit should yes#2023-03-0714:23borkdudedo you have a reason to believe it doesn't?#2023-03-0714:24imreNot at the moment, just reading up on the feature itself and saw that the examples use .clj as the file extension for the expansion files#2023-03-0714:24borkdudeThat's probably just from before#2023-03-0714:24borkdudePR welcome to change it#2023-03-0714:25imreare macroexpansion definitions distributed the same way with libs as other config/hooks?#2023-03-0714:26borkdudeyes#2023-03-0714:26imre> PR welcome to change it Will do once I confirm it works#2023-03-0714:44Braden ShepherdsonI'm having trouble with :clojure-lsp/unused-public-var with an admittedly rather complicated, multi-level def macro. there's two issues with the warnings: first, it can only track usage in Clojure code, and some of these are ^:exported and called from JS code. second, this macro generates 3 public, ^:exported defs for a list of inputs, and it's not an error to only use a subset of what it generates (even if all the uses were in Clojure and it could find them). I had thought configuring it with :linters {:clojure-lsp/unused-public-var {:exclude-when-defined-by ...}} would work, but it doesn't seem to. the relevant macros are here https://github.com/metabase/metabase/blob/master/src/metabase/domain_entities/malli.clj#L88 . see the usage examples in the docstrings, it takes a list of symbol [:path :in :map] pairs and generates a getter, setter, and some JS<->CLJS conversion helpers for each. I've tried putting the outer macro and all the inner macros in the :exclude-when-defined-by without success. there's a :macroexpand kondo rule for this as well, replacing it with three dummy defns for each row of input, if that changes anything. can I tweak the macroexpand code, or use a hook instead, and suppress this warning on the output somehow?#2023-03-0714:45borkdudecc @UKFSJSM38#2023-03-0714:50borkdude@UCY0GT0QM The clojure-lsp/* linters are implemented by #lsp - it might help asking questions over there#2023-03-0714:54Braden Shepherdsonoh I suppose those :exclude-when-defined-by etc. options are a clojure-lsp custom thing. I'll poke around in its implementation.#2023-03-0714:59ericdallo@UCY0GT0QM https://clojure-lsp.io/settings/#clojure-lspunused-public-varare the docs detailing all possible settings for that linter, but I'm wondering if we should exclude vars defined with ^:export meta, WDYT?#2023-03-0715:00Braden ShepherdsonI think that makes sense. ^:export is indicating that it's used out of scope, so even aside from the macro I wouldn't want an unused-public-var warning on (defn ^:export some-fn-called-from-js [] ...)#2023-03-0715:01ericdallothe issue with defined-by for macros is that relies on user defining :defined-by in clj-kondo hooks like https://github.com/nubank/state-flow/blob/master/resources/clj-kondo.exports/nubank/state-flow/nubank/state_flow.clj#L35 :/#2023-03-0715:02Braden Shepherdsonah, I see. so that sounds like my resolution is to use hooks instead of :macroexpand and set that rule accordingly.#2023-03-0715:02ericdalloYeah, makes sense, feel free to create a issue where we can discuss the implementation at clojure-lsp#2023-03-0715:02ericdalloyes, as a workaround that may work#2023-03-0715:03Braden Shepherdsonwell, that's separate from the ^:export thing. actually now that I think about it, that already works. there's a separate ^:exported function here with no warning about that. if I un-`^:export` it, I get an unused warning.#2023-03-0715:04ericdalloat nubank we have custom vars with a specific meta as well, so maybe we should allow user define metas to exclude, but if exports is a cljs/clj thing/standard, clojure-lsp should support OOTB#2023-03-0715:05Braden Shepherdsonshadow-cljs recently added a non-standard ^{:export-as "jsFunctionName"} option too, that should probably have the same semantics as ^:export (`^:export` is CLJS standard, not just shadow-cljs)#2023-03-0715:05ericdallooh, indeed we already have support for export did one year ago#2023-03-0715:05ericdallohttps://github.com/clojure-lsp/clojure-lsp/pull/753#2023-03-0715:06ericdalloyeah, probably should have more work to support export-as#2023-03-0715:06Braden Shepherdsonlet me try setting :export true on the dummy defns in my :macroexpand#2023-03-0715:07borkdude
(defn foo []
  {:export true} ...)
might help
#2023-03-0715:08borkdudealthought from the linked PR I don't see how metadata is picked up#2023-03-0715:18Braden Shepherdsonokay, metadata after the args doesn't work (not sure why) but ~(vary-meta sym assoc :export true) on the defns in the :macroexpand does work.#2023-03-0715:30Braden ShepherdsonI think the only resulting action here should be documenting that the :exclude-when-defined-by only works if the :defined-by is set in the hook for that macro. I imagine plenty of libraries with defn-ish macros have that built in, but if you're building something of your own then it's weird that the option doesn't work.#2023-03-0715:31ericdalloagreed, TBH I didn't pay attention that :exclude-when-defined-by could be used by macros, worth mentioning that#2023-03-0715:41Braden ShepherdsonI can file an issue with clojure-lsp's docs if you like.#2023-03-0715:42ericdalloSure!#2023-03-0716:01Braden ShepherdsonI lied there's also the :export-as thing. https://github.com/clojure-lsp/clojure-lsp/issues/1511 https://github.com/clojure-lsp/clojure-lsp/issues/1512#2023-03-0716:27ericdallothanks, I mentioned in the last one how it should be fixed, LMK if you wanna work on that#2023-03-0717:58Braden ShepherdsonI haven't actually tripped over it yet, but probably will later this week or next week. I'll fix it when I do, or when I've got some idle time.#2023-03-0810:41AkizHi, I have updated Malli to the latest version and clj-kondo now reports “insufficient input” (that map in image for example). This is the schema: [:map {:closed true} [:name string?] [:description string?] [:created-by {:optional true} [:maybe string?]] [:id {:optional true} int?]]#2023-03-0810:41AkizThis is kondo’s config#2023-03-0810:43borkdudeCan you make a clj-kondo only repro that I can clone locally so I don’t have to copy or type code from screenshots? Then I’ll have a look later today#2023-03-0811:18AkizI don’t get this error in a new project, so I won’t even upload it. The definition in malli-types-clj/config.edn is same for both projects. I tried to delete clj-kondo .cache and also .lsp from the original project, no luck. Unfortunately I can’t share the original project and it is really complex, so there are a lot of variables. Do you have any idea where I could look?#2023-03-0812:14borkdudeIf you can't make a repro, I can't help you fix it, unfortunately, but maybe you can downgrade malli and ask in #CLDK6MFMK - seems like a downstream problem#2023-03-0812:46AkizInteresting, the downgrade didn’t help. So I thought to delete .clj-kondo/metosin and it worked (with old and new version as well).#2023-04-0720:02Noah Bogarthttps://github.com/metosin/malli/issues/865 here's the bug you ran into#2023-03-0815:08Noah BogartHook question: I have a macro that acts like def but takes a namespaced symbol and strips the namespace from it and then uses def to make a var: (defrule style/some-var ...) macroexpands to (simplified): (def some-var ...). i wrote a simple hook for this, and for some reason, clj-kondo/clojure-lsp seem to treat the whole block now as a single unit instead of parsing/analyzing each sub expression:
(ns hooks.noahtheduke.splint.rules
  (:require
    [clj-kondo.hooks-api :as api]))

(defn defrule-hook
  [{:keys [node]}]
  (let [[rule-name & body] (next (:children node))
        node (api/list-node (list* (api/token-node 'def)
                                   (api/token-node (symbol (name (api/sexpr rule-name))))
                                   body))]
    {:node node}))
#2023-03-0815:09Noah Bogart#2023-03-0815:10Noah Bogartthat's a demonstration of "show docs" called on ->violation displaying the docs for this whole top-level form#2023-03-0815:10Noah Bogartis there a better way to do this?#2023-03-0815:12Noah Bogartif I switch the hook to (api/token-node 'defrule) instead of 'def , then go to definition and show docs work but the whole form has an "unresolved symbol: sorted-rules-require" error#2023-03-0815:30borkdudeWhy write such a macro in the first place? Maybe ^:dev name could also work?#2023-03-0815:31borkduderegardless of that, let's take a look at your hook code#2023-03-0815:32Noah Bogart🤷 it's the api i've decided on, it's shortest and simplest and communicates the intentions#2023-03-0815:32borkdudeThis is wrong:
(list* (api/token-node 'def)
                                   (api/token-node (symbol (name (api/sexpr rule-name))))
#2023-03-0815:32borkdudelist* expects the last thing to be a collection of nodes#2023-03-0815:33Noah BogartI have "body" at the end, doesn't that expand properly?#2023-03-0815:33borkdudeI recommend using (println node) before you return it, and then execute this on the command line#2023-03-0815:33borkdudethen you will see what I mean probably#2023-03-0815:33borkdudeoh yes, body, I missed that#2023-03-0815:34borkdudeI think you can fix stuff by preserving more original locations via the metadata#2023-03-0815:34borkdudewith with-meta or vary-meta#2023-03-0815:44Noah Bogart
(defn defrule-hook
  [{:keys [node]}]
  (let [[defrule rule-name & body] (:children node)
        new-node (api/list-node
                   (list* (with-meta (api/token-node 'def) (meta defrule))
                          (with-meta (api/token-node (symbol (name (api/sexpr rule-name))))
                                     (meta rule-name))
                          body))]
    {:node (with-meta new-node (meta node))}))
#2023-03-0815:44Noah Bogartthere we go, that works#2023-03-0815:44Noah Bogartthank you for the help#2023-03-0821:31Patrick BrownI’ve got a clj-kondo/clojure-lsp issue with emacs. It stopped working. I did something, what I do not know. All components work in isolation, just not together. Deleting and reinstalling did not help. How do I go about troubleshooting this? I’m a little lost in where to start digging. Any advice is appreciated.#2023-03-0821:43borkdudeIs it possible to create a repro repository?#2023-03-0821:44borkdudeAre you running clojure-lsp or do you also run clj-kondo separately somehow?#2023-03-0821:48Patrick BrownI could make a repro repo, but I think the issue is much deeper. I’ve gone into the repro repo I sent you when I had issues with defn-spec. It doesn’t work. I’ve messed something up at the global/emacs config level or something else deeper in the well than the project. That’s why I’m a little lost as to how I should continue#2023-03-0821:51borkdudethe first thing I usually recommend people to try it clj-kondo on the command line#2023-03-0821:52borkdudeare you able to run this:
clj-kondo --lint src
#2023-03-0821:52Patrick BrownIt lints#2023-03-0821:52borkdudeand maybe clojure-lsp as a command line tool:
clojure-lsp diagnostics
#2023-03-0821:53Patrick BrownIt gives me an output similar to linting filled with how not perfect my code is#2023-03-0821:54borkdudein your emacs config folder, can you maybe do this: mv elpa elpa.bak#2023-03-0821:54borkdudeand then restart your emacs#2023-03-0821:55Patrick BrownI’m assuming that’s the same as moving my straight repos folder.?#2023-03-0821:55borkdudeI guess so. This reminds me. #CPABC1H61 has a minimal emacs config to debug things#2023-03-0821:56borkdudeyou could try that one. @UKFSJSM38 knows where it is probably#2023-03-0821:56borkdudehttps://clojure-lsp.io/troubleshooting/#2023-03-0821:57ericdalloYes, and if it's a problem with not even starting clojure-lsp check this https://emacs-lsp.github.io/lsp-mode/page/troubleshooting/#2023-03-0821:59Patrick BrownLsp starts, the server info gives me a clojure-lsp version of 2.27, and lsp of 2.17, the classpath settings is nil.#2023-03-0821:59Patrick Brownscratch that, clj-kondo of 2.17#2023-03-0822:00ericdalloI think both versions are wrong, they should be dates#2023-03-0822:00Patrick BrownYes, I was referring to the dates, feb 17th and 27th#2023-03-0822:00Patrick BrownI can’t copy the server info, because I’m not sure how to open it in a proper buffer.#2023-03-0822:01borkdudego to *Messages*#2023-03-0822:01ericdalloYou can just click the mini buffer or do what borkdude said
#2023-03-0822:02Patrick BrownDuh, not a proud moment
:client-settings
 {:dependency-scheme "jar",
  :show-docs-arity-on-same-line? true,
  :text-document-sync-kind nil,
  :source-paths nil,
  :source-aliases nil,
  :cljfmt-config-path ".cljfmt.edn",
  :document-formatting? true,
  :document-range-formatting? true},
 :project-root-uri "file:///home/pat/m",
 :port "NREPL only available on :debug profile (`bb debug-cli`)",
 :project-settings {},
 :server-version "2023.02.27-13.12.12",
 :clj-kondo-version "2023.02.17",
 :log-path "/tmp/clojure-lsp.3157811663365747466.out",
 :classpath-settings nil}
 :client-settings
 {:dependency-scheme "jar",
  :show-docs-arity-on-same-line? true,
  :text-document-sync-kind nil,
  :source-paths nil,
  :source-aliases nil,
  :cljfmt-config-path ".cljfmt.edn",
  :document-formatting? true,
  :document-range-formatting? true},
 :project-root-uri "file:///home/pat/m",
 :port "NREPL only available on :debug profile (`bb debug-cli`)",
 :project-settings {},
 :server-version "2023.02.27-13.12.12",
 :clj-kondo-version "2023.02.17",
 :log-path "/tmp/clojure-lsp.3157811663365747466.out",
 :classpath-settings nil}
#2023-03-0822:04ericdalloEverything looks good, check if project-root-uri really matches your project root#2023-03-0822:06Patrick BrownIt does. I’m doing a proper full on reinstall of my emacs deps as borkdude outlined. It feels like I must have messed something up with my emacs config, but for the life of my I don’t remember touching it.#2023-03-0822:07borkdude@U036UJBDM5G I don't want to sound patronizing, but do you save your emacs config in version control? I even save my entire elpa directory in version control since 2013 haha#2023-03-0822:07Patrick BrownI have all my configs, but I git ignore my autodownloaded deps.#2023-03-0822:07borkdudeI've had too many weird issues before that and decided to do it the blunt way#2023-03-0822:08Patrick BrownIf that turns out to be my problem, I may jump on that ship.#2023-03-0822:08borkdudeI'm not using straight.el etc, it may have better version management#2023-03-0822:09Patrick BrownIt supposed to immutable like nix, but all I know is I just add :straight t to my use-package and it works.#2023-03-0822:09borkdudeI've had issues with .elc files before, when I removed those, emacs re-compiled the .el files and suddenly a problem was fixed#2023-03-0822:10Patrick BrownThe same has happened with straight many times. This time I deleted andything with clojure in the name and it didn’t help, but it costs nothing to go further.#2023-03-0822:11borkdude@UKFSJSM38 what was the minimal emacs project to install clojure-lsp / lsp-mode again? it helped me find the weird delay problem at the time#2023-03-0822:14ericdallohttps://emacs-lsp.github.io/lsp-mode/page/troubleshooting/#check-if-any-package-or-wrong-config-could-be-causing-the-issue#2023-03-0822:17borkdudeah yes, @U036UJBDM5G you could try that file instead of init.el and see if you can get things working#2023-03-0822:18Patrick BrownWell, no dice on the rebuilding emacs with fresh packages, and no dice on the minimal config.#2023-03-0822:21borkdudeis clojure-lsp on your path, can emacs find it?#2023-03-0822:21borkdudeelse lsp-mode will download it anyway right#2023-03-0822:22Patrick BrownI appreciate you both for coming out. HMU if you think of anything. I’m a frustrated dog, so maybe my dog and I should go outside for a walk with the beautiful weather we’re having. When I come back, I’m installing clojure-lsp and clj-kondo from source again, and launching with a custom command. That worked in the past. clojure lsp is there it just doesn’t seem to link with emacs, emacs knows it’s there, it knows my classpath. The problem lies somewhere in the middle.#2023-03-0822:23borkdudeenjoy#2023-03-0822:26ericdalloA simple project usually helps a lot debug such issues, I recommend testing with my https://github.com/ericdallo/clojure-sample project#2023-03-0823:45Patrick Brown@U04V15CAJ @UKFSJSM38 Thanks for all the help. After no luck with building from source. I went nuclear rm -rfed the f out of everything I could find, then I reinstalled things just like the readme brought my custom config back in piece by piece. I wish I had something smart to say… I’m just happy I can use my tooling again. Side note, I’ve grown way to reliant on tooling to be comfortable. Keep up the good work. I appreciate the quality things you make.#2023-03-0823:50ericdalloThanks! Glad it works now :)#2023-03-1000:33Sam Ritchiequestion on kondo invoked from a bb.edn task… I noticed that my warnings are not causing CI failure https://github.com/mentat-collective/emmy/actions/runs/4379015980/jobs/7664467312 here is my bb.edn:
{:pods {clj-kondo/clj-kondo {:version "2023.01.20"}}
 :tasks
 {:requires ([pod.borkdude.clj-kondo :as clj-kondo])

  lint
  {:doc "Lint with clj-kondo."
   :task (clj-kondo/print!
          (clj-kondo/run! {:lint ["src" "test"]}))}}}
#2023-03-1014:06borkdudeThis is because you're running clj-kondo manually, you should manually handle errors and failures#2023-03-1014:06borkdudebut it's now recommended to use this instead of the pod directly: https://github.com/clj-kondo/clj-kondo-bb/blob/246ac4c09ac32008025d7e8da28211e448b9fc91/src/clj_kondo/core.bb#L13#2023-03-1014:43Sam Ritchienice, like
lint
{:doc "Lint with clj-kondo."
   :task (clj-kondo/exec {:lint ["src" "test"]})}
?
#2023-03-1014:44borkdude
:task (exec 'clj-kondo.core/exec)
:exec-args {:lint ["src" "test"]}
#2023-03-1014:45borkdudeThis might need better docs 😅#2023-03-1014:45borkdudeYou can then pass additional args with --lint foo bar on the command line#2023-03-1014:45borkdudebut not all arguments are properly babashka.cli-ified#2023-03-1014:46Sam Ritchie
[sritchie@wintermute ~/code/clj/emmy (sritchie/docstrings)]$ bb lint
----- Error --------------------------------------------------------------------
Type:     java.lang.NullPointerException
Location: <expr>:20:1

----- Context ------------------------------------------------------------------
16: (when-not (resolve 'run)
17:   (intern *ns* 'run babashka.tasks/run))
18:
19: (when-not (resolve 'exec)
20:   (intern *ns* 'exec @(var babashka.tasks/exec)))
    ^---
21:
22: nil
23: (def lint (binding [
24:   babashka.tasks/*task* '{:name lint, :doc "Lint with clj-kondo.", :task (exec 'clj-kondo.core/exec), :exec-args {:lint ["src" "test"]}}]
25:   nil

----- Stack trace --------------------------------------------------------------
exec-af4cd7c4-a77a-487a-a098-1c4e132ebcc0/exec - <expr>:20:1
exec-af4cd7c4-a77a-487a-a098-1c4e132ebcc0      - <expr>:4:1
user-49a145ee-67a2-44ef-868b-b6368ff89c06      - <expr>:26:1
#2023-03-1014:47Sam RitchieThis is with
{:pods {clj-kondo/clj-kondo {:version "2023.01.20"}}
 :tasks
 {:requires ([pod.borkdude.clj-kondo :as clj-kondo])

  lint
  {:doc "Lint with clj-kondo."
   :task (exec 'clj-kondo.core/exec)
   :exec-args {:lint ["src" "test"]}}}}
#2023-03-1014:47borkdudeHave you added this dependency to your bb.edn?#2023-03-1014:47borkduderemove the pod stuff and add the dependency#2023-03-1014:47borkdudethe dependency being: https://github.com/clj-kondo/clj-kondo-bb#2023-03-1014:47borkdudeI'm still torn between "bb-clj-kondo" and "clj-kondo-bb"#2023-03-1014:48Sam Ritchiethat worked, thank you! time to upgrade all my projects…#2023-03-1014:49Sam RitchieI like the suffix version personally, mirroring the file extension#2023-03-1014:49borkduderight, thanks :)#2023-03-1014:49Sam RitchieI think you inspired me to do that for mathbox.cljs etc, and then I saw you moved back to dashes!#2023-03-1014:49borkdudeI first actually had http://clj-kondo.bb but then all kinds of apps made that into a hyperlink to a non-existing website facepalm#2023-03-1014:49Sam Ritchiehaha yes that was it#2023-03-1014:50Sam Ritchiehow did you get GitHub to syntax-highlight bb files as Clojure? or is it doing inference on the file contents?#2023-03-1014:50borkdudeby making bb popular enough? 😆#2023-03-1014:50borkdudeI guess eventually someone made a PR to this linguist thing#2023-03-1020:09Sam Ritchiehttps://github.com/mentat-collective/emmy/actions/runs/4388062311/jobs/7684113615#2023-03-1020:09Sam Ritchiethis is a bit strange, @borkdude… digging in now, but on CI, after this change,
Downloading: org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar from central
----- Error --------------------------------------------------------------------
Type:     clojure.lang.ExceptionInfo
Message:  Could not resolve symbol: exec
Phase:    analysis

Error: Process completed with exit code 1.
#2023-03-1020:10Sam Ritchielet me upgrade babaska there and see what happens#2023-03-1020:10borkdudeyes, upgrade babashka :)#2023-03-1020:10borkdudebabashka 0.8.156 😱 that's old :)#2023-03-1020:13Sam Ritchiehaha hadn’t done any gardening in the actions for a while#2023-03-1020:13borkdudebtw I use setup-clojure for almost everything in github actions now and just say: bb: latest#2023-03-1020:16Sam Ritchie
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Install babashka
        uses: just-sultanov/setup-babashka@v2
        with:
          version: '1.2.174'

      - name: Cache kondo directory
        uses: actions/cache@v2
        with:
          path: ~/.clj-kondo/.cache
          key: ${{ runner.os }}-kondo
          restore-keys: ${{ runner.os }}-kondo

      - name: Run clj-kondo
        run: bb lint --config '{:output {:pattern "::{{level}} file={{filename}},line={{row}},col={{col}}::{{message}}"}}'
time for me to upgrade this too!
#2023-03-1020:16Sam RitchieI bet latest would work here as well#2023-03-1020:17borkdudeIs this to please github with inline annotations? "::{{level}} file={{filename}},line={{row}},col={{col}}::{{message}}"}#2023-03-1020:17Sam Ritchiehttps://github.com/babashka/sci/blob/master/.github/workflows/ci.yml#L21#2023-03-1020:17Sam Ritchiewoah, look at this antique#2023-03-1020:17borkdudeaaaargh ;)#2023-03-1020:17borkdudehehe#2023-03-1020:17Sam Ritchie@borkdude yeah that’s right#2023-03-1020:17borkdudesuper cool#2023-03-1000:33Sam Ritchiewith the CLI tool, the default level fails on warn…
--fail-level <level>: minimum severity for exit with error code.  Supported values:
    warning, error.  The default level if unspecified is warning.
what change should I make to have the task set a nonzero exit code?
#2023-03-1003:00johnI tried bringing in an old library I wrote a while back that had some clj-kondo exports configured. https://github.com/johnmn3/dispacio/blob/master/.clj-kondo/test.clj @borkdude you helped me out with it in the past and added that test file. In my new project, I'm seeing this error:#2023-03-1014:07borkdudeHi. Can we discuss in a thread?#2023-03-1014:08borkdudeCan you point me to the code of your hook?#2023-03-1014:09johnthis one? https://github.com/johnmn3/dispacio/blob/master/resources/clj-kondo.exports/net.clojars.john/dispacio/dispacio/alpha/core.clj_kondo#2023-03-1014:12borkduderight, and what is wrong with this one?#2023-03-1014:12johnIt might just be a clojure dependency issue#2023-03-1014:13johnthat test file in there, I believe that's what is causing a downstream consuming project to cause that read-string error above#2023-03-1014:13borkdudeI will check out your dependency and run it locally#2023-03-1014:13johnand that's the only place I see it being used in the code base#2023-03-1014:14borkdude
$ clj-kondo --lint .clj-kondo/test.clj
linting took 31ms, errors: 0, warnings: 0
#2023-03-1014:14borkdudethe test.clj file isn't exposed to other libraries since it's not on your exported files#2023-03-1014:15johnWas just about to ask that 🙂#2023-03-1014:15borkdudeonly what is inside clj-kondo.exports is going into your jar#2023-03-1014:16johnwell all of my defp statements like that, they are correctly interpreting the defmethod syntax inside it, but the outer bracket has that red underscoe#2023-03-1014:16johnand it's complaining about the read-string unresolved symbol#2023-03-1014:16borkdudecan you make a repro of that in the test.clj file?#2023-03-1014:17johnIt's in clojurescript#2023-03-1014:17borkdudeI need a repro to look at#2023-03-1014:17johnwhich might be the problem. Let me try adding up to date clojure libs#2023-03-1014:17borkdudeis it in the dispacio library itself?#2023-03-1014:18johnNo it's a project I'm working on locally#2023-03-1014:18borkdudecan you make a screenshot of the surroundings? the first screenshot was very local and not informative#2023-03-1014:18borkdude(to me)#2023-03-1003:01johnWhich is because of:#2023-03-1003:01johnAnd so as you can see in that file, I've updated the file to include a require statement for clojure.edn#2023-03-1003:02johnAnd so I updated the dep in my project to the latest git hash for that repo, but I'm still seeing the error. Does clj-kondo only auto-checkout exports from clojar releases?#2023-03-1003:02johnOr will it work off the latest git hash as well?#2023-03-1003:17johnI have tried deleting my caches#2023-03-1016:27jakemccI ran into this earlier this week and I am wondering if building a clj-kondo checker would be possible? A check for invalid number of arguments to the function passed to update /`swap!` style functions.
(defn two-args
  [coll x]
  (conj coll x))

(update {:a [1]} :a two-args) ;; uh-oh, wrong number of args to two-args but not flagged

(two-args []) ;; flagged as invalid-arity
#2023-03-1016:31borkdudeyeah, I think we could do this in clj-kondo itself: arity checking for update#2023-03-1016:32borkdudefeel free to log an issue#2023-03-1100:00jakemcchttps://github.com/clj-kondo/clj-kondo/issues/2003#2023-03-1110:30borkdudeAlready supported on master#2023-03-1117:37jakemccso fast 🏃 gratitude-thank-you#2023-03-1017:06dotemacsDrive by message: thank you for clj-kondo! ❤️#2023-03-1411:09Emanuel RylkeI've put :config-in-comment {:linters {:unresolved-namespace {:level :off} :unused-binding {:level :off}}} into my clj-kondo config and that worked for disabling the unresolved namespace linter but not for the unused binding linter. is that how it is or did I do something dumb?#2023-03-1411:29borkdudeLet me try#2023-03-1411:30borkdudeThis works for me:
(ns dude
  {:clj-kondo/config '{:config-in-comment {:linters {:unresolved-namespace {:level :off}
                                                     :unused-binding {:level :off}}}}})


(comment
  (clojure.string/includes? "")
  (let [x 1]
    )
  )
#2023-03-1411:31borkdudecan you give a "counter" repro?#2023-03-1412:22Emanuel RylkeTurns out I was using an outdated version, after updating clj-kondo it now works. Sorry for the bother#2023-03-1412:23borkdudeno worries :)#2023-03-1518:10pavlosmelissinosIf I add (user/dev) in a rich comment block clj-kondo complains with warning: Unresolved namespace user. Are you missing a require? I think it's a common pattern and the user namespace should always be available from within a REPL (without the need for a require). Is this intentional/expected?#2023-03-1518:12borkdudeyou can disable that linter in an RCF with:
:config-in-comment {:linters {:unresolved-namespace {:level :off}}}
#2023-03-1518:13borkdudeor add :exclude [user] to that linter's config#2023-03-1518:29pavlosmelissinosSo it's expected, thanks! I wasn't sure if I should create an issue about it on Github.#2023-03-1518:29borkdudeit's kind of an edge case. normally clj-kondo expects that you have a require before you use a namespace#2023-03-1518:30pavlosmelissinosMakes sense 🙂#2023-03-1519:45seancorfieldYou could always write ((requiring-resolve 'user/dev)) 🙂#2023-03-1519:46seancorfield(I have a dev ns with that sort of code in -- I avoid user.clj to avoid auto-loading stuff -- and I use ((requiring-resolve 'dev/whatever)) in RCFs for reaching into that ns)#2023-03-1609:22Søren SjørupI’m getting this:
❯ echo '(import "")' | clj-kondo --lint -
<stdin>:0:0: error: Can't parse <stdin>, java.lang.NullPointerException
linting took 39ms, errors: 1, warnings: 0
❯ clj-kondo --version
clj-kondo v2023.02.17
Should I just report an issue on github, and try to fix it?
#2023-03-1609:28borkdudeThat isn't valid clojure, so do you mean: clj-kondo should not crash?#2023-03-1609:30Søren SjørupI would prefer a error message saying it’s not valid clojure.#2023-03-1609:31borkduderight. issue and/or PR welcome#2023-03-1609:32borkdudeThe catch-all linter we use for this is called :syntax#2023-03-1609:32Søren SjørupCool.#2023-03-1612:35joakimenIs there any way to ignore a given namespace in clj-kondo? Like, applying #_:clj-kondo/ignore to everything in a namespace, without pasting the ignore-string in front of every form. Sometimes I like to flesh out a program structure upfront (function signatures, variables, ..) while leaving the bodies empty (with a ;; TODO ), which obviously trips up the linting. How do you guys work around this during WIP-stages of things?#2023-03-1612:37borkdudeYou can do either metadata on the ns or use :config-in-ns#2023-03-1612:37borkdudeor you can use :output :exclude-files#2023-03-1612:38borkdudeSee https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md and https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#2023-03-1612:39joakimenSpot on. That was a trove of documentation i somehow missed#2023-03-1612:40borkdudeI'm currently working on an easier mode to silence everything in a macro. E.g. {:clj-kondo/ignore true} and {:clj-kondo/ignore [:unresolved-symbol]}#2023-03-1612:40borkdudehere is a small demo: https://twitter.com/borkdude/status/1636108402043518981 but we could have the same for a namespace maybe#2023-03-1613:03joakimenThanks again for the help! Worked nicely with namespace metadata, though with specific rules. Will keep an eye on #C06MAR553 for updates then, a one-shot rule to ignore everything would be practical indeed#2023-03-1713:39borkdude#2023-03-1714:37borkdudeTo get access to the newest features of clj-kondo when used via clojure-lsp, you can use this technique: https://clojurians.slack.com/archives/CPABC1H61/p1678740112686219#2023-03-1810:14borkdudeSomeone just pointed me to phind, an AI-powered technical search engine. I asked it how to configure clj-kondo for a def-like macro: https://www.phind.com/search?q=How%20to%20configure%20clj-kondo%20for%20def-like%20macro&amp;source=searchbox Quit good actually ;)#2023-03-1811:35seriogathe most impressive that it is aware of newest kondo features#2023-03-1811:38borkdudeindeed!#2023-03-1911:16borkdudeWhen using clojure-lsp, I found that the linting is quite laggy compared to using clj-kondo via flycheck-clj-kondo directly. Therefore I wrote these recommendations, for those who also experience this: https://github.com/clj-kondo/clj-kondo/blob/master/doc/editor-integration.md#clojure-lsp#2023-03-1916:35ikitommiwhat would be a clj-kondo type-hint for homogenous map? eg. map with :string keys and :boolean values. Also, is there a way to mix homogenous and heterogenous maps? e.g. map with :x :int, :y :int and rest with :string keys and :boolean values?#2023-03-1916:36ikitommitrying to map this from malli:
(m/validate
 [:map
  [:x :int]
  [:y :int]
  [::m/default [:map-of :string :boolean]]]
 {:x 1, :y 2, "kikka" true})
; => true
#2023-03-1916:36borkdudethere is no way to describe the contents of a collection type in clj-kondo currently#2023-03-1916:36borkdudeso just :map #2023-03-1916:37ikitommiok, I’ll remove the ?? from the code then.
(defmethod accept :map-of [_ _ _ _] :map) ;;??
#2023-03-1916:37ikitommiI’ll write an issue#2023-03-1916:37borkdude:)#2023-03-1920:47genmeblogHow to be sure if my hook is loaded and executed from flycheck emacs or command line?#2023-03-1920:53genmeblogTo give more context. Trying to add clj-kondo config to a library (there are plenty of symbols created by macros). • clj-kondo.exports contains the following:
tsl@st-00994-1:~/clojure/fastmath/resources/clj-kondo.exports/generateme/fastmath$ ls
config.edn  hooks
tsl@st-00994-1:~/clojure/fastmath/resources/clj-kondo.exports/generateme/fastmath$ cat config.edn
{:hooks {:analyze-call {fastmath.core/+ hooks.fastmath.core.primitive/call}}}
tsl@st-00994-1:~/clojure/fastmath/resources/clj-kondo.exports/generateme/fastmath$ cd hooks/fastmath/core/
tsl@st-00994-1:~/clojure/fastmath/resources/clj-kondo.exports/generateme/fastmath/hooks/fastmath/core$ ls
primitive.clj
tsl@st-00994-1:~/clojure/fastmath/resources/clj-kondo.exports/generateme/fastmath/hooks/fastmath/core$ cat primitive.clj

(ns hooks.fastmath.core.primitive
  (:require [clj-kondo.hooks-api :as api]))

(defn call
  [{:keys [node]}]
  {:node (api/list-node (list* (rest (:children node))))})
• .clj-kondo - local config includes it:
tsl@st-00994-1:~/clojure/fastmath/.clj-kondo$ cat config.edn
{:config-in-call {fastmath.core/variadic-proxy {:ignore [:unresolved-symbol]}
                  fastmath.core/primitivemath-proxy {:ignore [:unresolved-symbol]}
                  fastmath.core/variadic-predicate-proxy {:ignore [:unresolved-symbol]}
                  fastmath.core/fastmath-proxy {:ignore [:unresolved-symbol]}}
 :config-paths ["../resources/clj-kondo.exports/generateme/fastmath"]}
However I don't see any effect. I tried to add println inside a hook call and still nothing.
#2023-03-1922:06genmebloglooks like :config-paths is not loading additional configs...#2023-03-2009:18genmeblogomg... it magically started working 😕#2023-03-2009:20borkdude@U1EP3BZ3Q are you using clj-kondo via clojure-lsp?#2023-03-2009:21borkdudeyou might have to restart the lsp server to pick up the new config, maybe. but good to know that it works#2023-03-2009:38genmeblogNo, I don't use lsp (due to lagging), barebone clj-kondo.#2023-03-2009:40genmeblogOne more question regardinng configuration in clj-kondo.exports . Is it loaded automatically when someone has a library as a dependency or should I force loading? It's not clear to me.#2023-03-2009:43borkdude@U1EP3BZ3Q when you use your library with exported configs, you should do:
clj-kondo --lint "$(clj -Spath)" --dependencies --copy-configs
to analyze deps + copy the configs from them
#2023-03-2009:43borkdudeclojure-lsp does this automatically#2023-03-2011:18genmeblogHit another case I don't understad. One namespace produces a function throgh some macro, say pow. Another namespace requires such namespace as m. Then (m/pow 10 2) is marked as Unresolved var. So I added a hook which checks arity of the call. This hook is called and arity is verified. But still unresolved var is reported - how to learn clj-kondo that m/pow is valid?#2023-03-2011:19genmeblogThis warning disappears when I clear the .cache folder.#2023-03-2011:21borkdudeDo you have a config for the macro which defines that var?#2023-03-2011:21genmeblogI have only hook.#2023-03-2011:21borkdudeYou get this warning because kondo doesn’t know about the definition of that var in that namespace #2023-03-2011:22genmeblogIs analyze-call enough or not?#2023-03-2011:22borkdudeI will come back to this in an hour, afk now#2023-03-2011:23genmeblogsure!#2023-03-2011:24borkdudeI think you just need to re-lint your dependencies once again once you have the config in place #2023-03-2011:35genmeblogAfter re-lint, the reappear. Maybe minimal example:#2023-03-2011:36genmeblogNo errors when linting below:
(ns some.a
  ;; get rid of macro call and local call to symbol1
  {:clj-kondo/config '{:config-in-call {some.a/emit-some-symbol {:ignore [:unresolved-symbol]}}
                       :linters {:unresolved-symbol {:exclude [symbol1]}}}})

(defmacro emit-some-symbol
  [sym]
  `(defn ~sym
     ([] ~(str "I'm a " sym))
     ([z#] (str (~sym) " + " z#))))

(emit-some-symbol symbol1)
(emit-some-symbol symbol2)
(emit-some-symbol symbol3)

(symbol1)
(symbol1 23)
#2023-03-2011:36genmeblogUnresolved vars here
(ns some.b
  {:clj-kondo/config '{:hooks {:analyze-call {some.a/symbol1 hook.some.symbols/call->do}}}}
  (:require [some.a :as a]))

;; unresolved var
(a/symbol1)
(a/symbol2 1)
(a/symbol3 22)
#2023-03-2011:41genmeblogwhere hooks are:
(ns hook.some.symbols
  (:require [clj-kondo.hooks-api :as api]))

(defn call->do
  [{:keys [node]}]
  (println node)
  {:node (api/list-node (list*
                         (api/token-node 'do)
                         (rest (:children node))))})
#2023-03-2011:41genmeblogand the result
$ clj-kondo --debug --lint src/some
[clj-kondo] Linting file: src/some/b.clj
<list: (a/symbol1)>
[clj-kondo] Linting file: src/some/a.clj
src/some/b.clj:6:2: warning: Unresolved var: a/symbol1
src/some/b.clj:7:2: warning: Unresolved var: a/symbol2
src/some/b.clj:8:2: warning: Unresolved var: a/symbol3
linting took 28ms, errors: 0, warnings: 3
#2023-03-2011:52borkdudeIs it possible to upload this minimal repro as a github repro?#2023-03-2011:53genmeblogYes!#2023-03-2012:11genmeblogHere it is: https://github.com/genmeblog/clj-kondo-unresolved-var#2023-03-2012:44borkdudeok, going to look into it now#2023-03-2012:55genmeblogThanks! The simplest would be ignore these vars but I think some custom linting (via analyze-call) would be great. Also it's not clear to me why in a namespace it's unresolved symbol but in b it's unresolved var.#2023-03-2012:56borkdudeWhy do you have a hook for the generated vars but not for the macro itself instead?#2023-03-2012:57borkdudeI think simply {:lint-as {clj-kondo-unresolved-var.a/emit-some-symbol clojure.core/defn}} would fix this without hooks#2023-03-2012:57borkdudeor rather def#2023-03-2012:58borkdude
(defmacro emit-some-symbol
  {:clj-kondo/lint-as 'clojure.core/def}
  [sym]
  `(defn ~sym
     ([] ~(str "I'm a " sym))
     ([z#] (str (~sym) " + " z#))))
#2023-03-2012:58borkdude(if you are using the newest clj-kondo already)#2023-03-2012:58genmeblogyes, I'm using the latest one.#2023-03-2013:00borkdudeso the above snippet would fix it all I think, just remove all the rest of the config#2023-03-2013:01borkdudeor this is even better maybe:
(defmacro emit-some-symbol
  {:clj-kondo/lint-as 'clojure.core/declare}
  [sym]
  `(defn ~sym
     ([] ~(str "I'm a " sym))
     ([z#] (str (~sym) " + " z#))))
#2023-03-2013:02borkdudesince then it won't get linted as an uninitalized var#2023-03-2013:02borkdudeso the idea is: you write hooks/config for a macro-expansion, not every macro usage#2023-03-2013:03genmeblogwell... it's not that easy 🙂 I have another example, what if my macro emits bunch of defn based on a list of symbols? Or a macro which generates macro which generates definitions (primitive.math case).#2023-03-2013:03genmeblogAnyway - I'll experiment and probably let you know.#2023-03-2013:06borkdudeyou can also ignore a whole bunch of stuff: {:unresolved-var {:exclude [the-ns-with-generated-syms]}}#2023-03-2013:07borkdudeand you can use the :macroexpand hook (similar to analyze-call) to paste the macro almost-verbatim-but-stripped-down-so-it-doesn't-do-any-side-effects#2023-03-2013:07borkdudeor you can paste a bunch of (declare sym-a sym-b) in the ns if you want clj-kondo to recognize the vars properly#2023-03-2014:13genmeblogthanks! Declare unnecessarily pollutes the namespace, excluding namespace removes linting (but we need linting). I'll experiment with :macroexpand probably...#2023-03-2014:14genmeblogIt would be great to say: here is the list of symbols, treat them as functions, they are defined.#2023-03-2014:21borkdudethis is what {:lint-as {your-macro clojure.core/declare}} will do#2023-03-2014:23borkdudeor a hook that expands into a declare calls#2023-03-2014:25genmeblogyep, this is the solution. As I mentioned I have more sophisticated macros, like: (primitivemath-proxy :one zero? isZero) which is translated into zero? calling some Java class. Anyway - macroexpand which emits declare will be probably best solution.#2023-03-2014:30genmeblogAaaaand this works! Thanks for your time!#2023-03-2014:35borkdude👍#2023-03-2014:36genmeblogI learned a lot about clj-kondo today 🙂#2023-03-2014:38borkdudecool! hope it wasn't too bad ;)#2023-03-2014:42genmeblogno, no, when you overcome some initial (wrong) assumptions it goes quite well 🙂#2023-03-2015:05juhoteperiI wanted to get a warning for direct @mui/material requires which can't be optimized properly by Closure and I found that it is possible without a custom linter by using :discouraged-namespace:
{:ns-groups [{:pattern "^@mui/material$"
              :name mui}]
 :linters {:discouraged-namespace {mui {:message "Direct require on \"@mui-material/material\" can't be optimized by Closure DCE."}}}
#2023-03-2015:12borkdude"It is possible" so this is just to confirm that it works like you want right? :)#2023-03-2015:12borkdudenice#2023-03-2015:20juhoteperiYeah#2023-03-2015:20juhoteperiAn example to others 🙂#2023-03-2015:21juhoteperiThough it seemed that I couldn't use a string key on the linter config directly, but it works through :ns-groups#2023-03-2015:21borkduderight, nice workaround#2023-03-2015:49emccueIs there a way for clj-kondo to reason about the namespace hierarchy? I want to enforce that any namespace com.company.comp where there is com.company.comp.routes cannot be required from any other namespace where there is also a com.company.comp2.routes#2023-03-2016:00borkdudeI think you can do this with a combination of :discouraged-namespace and :ns-groups#2023-03-2016:01borkdudebut not sure if I understood your exact problem#2023-03-2016:57emccueHmm#2023-03-2016:57emccuei'll have to give it a shot#2023-03-2016:57emccuebasically what I am trying to do is enforce some "module" boundaries#2023-03-2016:58emccueand if a namespace group has routes I assume want everything in it to stay as a "leaf" in the project#2023-03-2017:00borkdudeAre you using clojure-lsp?#2023-03-2017:00borkdudeI think it has a project integrated that can do this#2023-03-2017:01emccueIm sketching out a "clean slate" codebase, but ive not been using lsp#2023-03-2017:02emccueno special reason, just in cursive land#2023-03-2017:12borkdudewell, clj-kondo has :discouraged-namespace : https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#discouraged-namespace you can combine this with config-in-ns and ns-groups to maybe do what you want#2023-03-2017:13borkdudeand otherwise there is also the analysis output: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md so you can write your own verifications on that, programmatically#2023-03-2017:07sheluchinIs it possible/within scope for clj-kondo to provide warnings when you're writing EDN which should satisfy some particular external spec? I've been writing vega-lite specs in Clerk and Reveal and jumping to the Vega web editor to get feedback about violations against the JSON Schema spec https://vega.github.io/schema/vega-lite/v5.json#2023-03-2122:34borkdude4 years ago: 🎂#2023-03-2206:23epHi, I’ve defined a few hooks in some repo configs and now would like to export them. What’s the correct way to set them up so they can still be used within the project itself? Do I still need to “copy-configs” to the repo’s .clj-kondo/ or can it be configured to find them in the exported resources location to avoid the duplication? I’ve searched through here and looked at the docs but haven’t had luck. #2023-03-2208:53borkdude@UNNNQBC7N You can do this by adding :config-paths ["../resources/clj-kondo.exports/your.org/your.lib"] in your .clj-kondo/config.edn#2023-03-2211:14ep:man-facepalming: thank you #2023-03-2211:15borkdude@UNNNQBC7N No worries, this is a common question and perhaps the documentation isn't clear on this. Feel free to PR some clarifications#2023-03-2218:29epWill gladly do so#2023-03-2219:34borkdudeI created an example of how to make an AST from clj-kondo analysis and rewrite-clj: https://github.com/clj-kondo/clj-kondo/tree/master/analysis#ast#2023-03-2219:37borkdude@U0FR82FU1 I think you asked about a similar thing once.#2023-03-2310:23teawaterwireis there a way to remove these warnings, without removing the unresolved symbole rule?#2023-03-2310:32borkdudeI need more context. Is this a .cljc file?#2023-03-2310:33borkdudeAnd/or: can you provide this code, with minimal but complete context in a .cljs or .cljc file? Then I would be able to say moe#2023-03-2310:39teawaterwirecljs file
(ns app.magic
  (:require 
   [re-frame.core :as rf]
   [promesa.core :as p]
   [clojure.string :as str]
   [app.utils :refer [j->c]]
   [app.config :refer [env]]
   [app.matrix :as matrix]
   ["ethers" :refer [ethers]]
   ["magic-sdk" :refer [Magic]]
   ["@magic-ext/webauthn" :refer [WebAuthnExtension]]))

(defonce magic (new Magic (:magic-key env)
                (clj->js {:extensions [(new WebAuthnExtension)]})))

(defonce magic-provider (new (.. ethers -providers -Web3Provider) (.-rpcProvider magic)))
#2023-03-2310:42teawaterwirethis file: https://github.com/teawaterwire/web4th/blob/master/src/app/magic.cljs#2023-03-2310:44borkdudeok, I see the issue. this is a workaround:
(defonce magic-provider (let [provider (.. ethers -providers -Web3Provider)]
                          (new provider (.-rpcProvider magic))))
#2023-03-2310:44borkdudeFeel free to post an issue about this#2023-03-2310:51teawaterwiregreat thanks will create an issue 👍#2023-03-2416:09rafaeldelboniHey I was using clj-kondo analysis :filename to try to get the source file in github, but for clojurescript I'm having a "problem" For this two examples the filename only shows: • cljs/analyzer/api.cljscljs/analyzer/passes.cljs But the folder structure before the cljs folder is different: • https://github.com/clojure/clojurescript/blob/r1.11.60/src/main/clojure/cljs/analyzer/api.cljchttps://github.com/clojure/clojurescript/blob/r1.11.60/src/main/cljs/cljs/analyzer/passes.cljc Is there a way to get a bigger path in :filename or infer this difference in any way?#2023-03-2416:26borkdudeI think this comes from a jar file. You can get a longer name by setting :canonical-file-names true (or so, see docs)#2023-03-2416:28rafaeldelboniYou mean :canonical-paths ?#2023-03-2416:28borkdudeI think so#2023-03-2416:29rafaeldelbonicool I will give it a try#2023-03-2416:33rafaeldelboninah, it appends the source of the information like: "/Users/rafael.delboni/.m2/repository/org/clojure/clojurescript/1.11.60/clojurescript-1.11.60.jar:cljs/analyzer/api.cljc"#2023-03-2416:34rafaeldelbonibut that's fine, I'm using this tool in a non intended way I think hahaha#2023-03-2416:34borkdudeI don't understand what else you are missing, what more is there to know about the location where it came from#2023-03-2416:35rafaeldelboniI'm building a web app with the analysis data extracted from kondo, one feature I was adding was a link to the source in the github of the analysis#2023-03-2416:36borkdudeTake a look at quickdoc, it builds documentation with source links to github: https://github.com/borkdude/quickdoc/blob/main/API.md But you need to provide the github repo yourself as this is not part of the analyzed data#2023-03-2416:36borkdude> I'm building a web app with the analysis data extracted from kondo Very cool ❤️#2023-03-2416:37rafaeldelboniIt's just a study of mine over spa https://rafael.delboni.cc/clojuredocs-helix/#/org.clojure It works for clojure, but not for clojurescript#2023-03-2416:43borkdudeif you want to have more accurate locations, it's better to git clone clojurescript and then analyze the source folders from clojurescript's repo#2023-03-2416:43borkdudeand then derive the github links from the filenames#2023-03-2416:44rafaeldelbonicool, I will probably pivot to this instead downloading the jars 🙂, similar to quickdoc thanks#2023-03-2611:33borkdudeUpdated clj-kondo's clojure-lsp documentation: - How to get snappier feedback - How to reduce noise / distracting features - How to run a specific version of clojure-lsp and/or clj-kondo in a JVM https://github.com/clj-kondo/clj-kondo/blob/master/doc/editor-integration.md#clojure-lsp#2023-03-2615:24borkdudeNote that the some of the above requires clojure-lsp from master, which you can run according to last bit in those docs#2023-03-2709:34Jacob Taylor-HindleHey all 👋 Is there any way I can warn against the usage of specific tagged literals (e.g. #inst)? I imagine I have to create a custom lint but wanted to check to make sure I'm not missing anything.#2023-03-2709:39borkdude@U04SBRBM4CF currently there is :config-in-tag but I'm not sure how this lets you warn on the usage of that tag :)#2023-03-2709:41borkdude
:config-in-tag {inst {...}}
#2023-03-2709:41borkdudemaybe we need a new issue for this#2023-03-2709:47Jacob Taylor-HindleThanks! I'll take a look 🙂#2023-03-2709:48borkdude:discouraged-tag would make sense, since we have it for -var and -namespace#2023-03-2711:32Jacob Taylor-HindleCreated an issue: https://github.com/clj-kondo/clj-kondo/issues/2030#2023-03-2711:34borkdudeIf anyone wants to have a go at the PR for this: it's pretty straightforward since it's similar to existing linters.#2023-03-2712:11Jacob Taylor-HindleI'm happy to take a look! Are there any PRs you can recommend I use as a reference?#2023-03-2712:12borkdudeYes, the implementation of :discouraged-var etc#2023-03-2712:12borkdudejust use search on github and look at the code#2023-03-2716:06Jacob Taylor-HindleHad a first go at it, though it's not fully working yet - https://github.com/clj-kondo/clj-kondo/pull/2031#2023-03-2716:07borkdudeCool! I think it make sense to do the check at the same spot where we handle :config-in-tag - this should catch all occurrences#2023-03-2716:07borkdudehttps://github.com/clj-kondo/clj-kondo/blob/1de6d9d2862f8052b1137f2d36c32d5ddb409cbd/src/clj_kondo/impl/analyzer.clj#L2594#2023-03-2716:08Jason WhitlarkWrong “@Ja” 😆#2023-03-2716:08borkdudeWhoops!#2023-03-2914:01Jacob Taylor-HindleThanks for the quick turnaround @U04V15CAJ 🙂#2023-03-2914:08borkdude@U04SBRBM4CF you too!#2023-03-2711:34borkdudeIf anyone wants to have a go at the PR for this: it's pretty straightforward since it's similar to existing linters.#2023-03-2809:52igrishaevCan anyone remind me please how to fix/bypass this message: "unsupported binding form". The code I have is:
(let [{promoter-oid :oid}
        (system/with-tx [tx :admin-db]
          (system/create-resource tx
                                  "Promoter"
                                  {:name "Test"}))
#2023-03-2809:54borkdude@U1WAUKQ3E This is presumably because you have:
:lint-as {system/with-tx clojure.core/let}
?
#2023-03-2809:55igrishaevah, right, I haven't check that! Thank you!#2023-03-2809:57borkdudehmm, no that isn't it#2023-03-2809:57borkdudecan you provide a full self-contained example and your corresponding config?#2023-03-2809:58borkdudeThis works fine for me:
(ns scratch
  {:clj-kondo/config '{:lint-as {system/with-tx clojure.core/let}}}
  (:require [system :as system]))



(let [{promoter-oid :oid}
      (system/with-tx [tx :admin-db]
        (system/create-resource tx
                                "Promoter"
                                {:name "Test"}))])
#2023-03-2810:01igrishaevI’m afk for a while, will post updates soon#2023-03-2913:17igrishaevSo I removed this macro from the lint-as sections and it worked. Then I added it into the unresolved-symbol section to mute warning for tx vars and similar. Thank you again!#2023-03-2913:19borkdude@U1WAUKQ3E I don't understand. This worked fine: https://clojurians.slack.com/archives/CHY97NXE2/p1679997538459489?thread_ts=1679997175.930999&amp;cid=CHY97NXE2#2023-03-2913:19borkdudeWhy did it not work for you?#2023-03-2913:21igrishaevHm, I don't know for sure, the but the current approach is completely fine to me. I'm not sure that linting this macros as let would be fine as it might accept up to three arguments in the first vector.#2023-03-2913:24borkdudeoh I see :)#2023-03-2913:24borkdude👍#2023-03-2809:53igrishaevSo the linter doesn't like the :admin-db key#2023-03-3012:51ericdalloIs this a known kondo false-positive?#2023-03-3012:51borkdudepossibly#2023-03-3012:51ericdallo
(spec/keys :req [:a]
           :gen #()) ;; unknown option :gen
#2023-03-3012:51borkdudeissue + fix welcome. there's maybe a missing option#2023-03-3012:52borkdudehttps://github.com/clj-kondo/clj-kondo/blob/d98bff2a20c2bc803ebda013f1cabe2f8dea8a29/src/clj_kondo/impl/analyzer/spec.clj#L13#2023-03-3012:52borkdudeno sorry, here: https://github.com/clj-kondo/clj-kondo/blob/d98bff2a20c2bc803ebda013f1cabe2f8dea8a29/src/clj_kondo/impl/analyzer/spec.clj#L44#2023-03-3012:53ericdallothanks! A co-worker reported, will ask him if he's willing to open the issue + possible PR#2023-03-3012:53borkdudecool. I didn't know about the :gen option#2023-03-3012:53ericdalloneither I!#2023-03-3021:36André CamargoHey there! I've cooked a https://github.com/clj-kondo/clj-kondo/pull/2032 for this.#2023-03-3021:37borkdude@U04CAPVN1HS Thanks! I'll check tomorrow#2023-03-3122:30DrLjótssonI am using Calva and am writing a function that will wrap re-frame/reg-sub . Calva recognizes unused re-frame subs and clicking on the keyword in (re-frame/subscribe [:foo/bar]brings be to the sub definition. I guess this is powered by clj-kondo? Is there a way to tell clj-kondo that my homegrown reg-sub function is also a re-frame subscription so it behaves in the same way? I tried :lint-as but that did not work.#2023-04-0110:07DrLjótssonNevermind! I botched my :lint-as declaration. It works as expected.#2023-04-0318:49borkdudeoh thanks for confirming!#2023-04-0318:49borkdudeIn the next version: :exclude-patterns in :unresolved-symbol , e.g. to suppress ?foo named variables in a macro usage. (cc @noprompt)#2023-04-0318:53Noah Bogartoh that's cool, would work great when paired with :config-in-call#2023-04-0318:53borkdudeAs you can see in the screenshot, you can attach the config directly on the macro#2023-04-0318:54borkdudebut if you don't control the macro then config-in-call works great too#2023-04-0319:00nopromptThat’s a nice way to do it 🙂#2023-04-0523:33James AmbergerHello. I have a shadow-cljs project and I am trying to tell kondo to understand defnc and other helix macros. I haven't had need of a deps.edn, my dependencies are in shadow-cljs.edn. What's the right way to do this?#2023-04-0602:52lilactownhelix includes configuration for this in the library itself. you should only need to run the clj-kondo command to copy configs
#2023-04-0602:53lilactownhttps://github.com/clj-kondo/clj-kondo/tree/master#project-setup#2023-04-0602:54lilactownif you're using shadow-cljs, I think that
$ clj-kondo --lint "$(shadow-cljs classpath)" --dependencies --parallel --copy-configs
will suffice
#2023-04-0606:17borkdudeyes, you need to ensure that a .clj-kondo directory exists first#2023-04-0611:27James AmbergerI added that advice to the README lilactown. Thanks everyone#2023-04-0603:27frankitoxAnyone knows how to use clj-kondo.hooks-api/reg-keyword!?#2023-04-0603:29frankitoxMy understanding is that if I do
(api/reg-keyword! (api/keyword-node :coco)
                  'app.core/hello-world)
Then when calling go to definition from lsp I should be able to navigate to hello-world function when the cursor is on the :coco keyword
#2023-04-0603:31frankitoxThis is in the context of a hook. I have something like this:
(defn my-hook [ast]
  (api/reg-keyword! (api/keyword-node :coco)
                    'app.core/hello-world)
  ast)
#2023-04-0606:18borkdude@U3UFFB420 you need to replace the keyword in the node with the reg-keyword one#2023-04-0613:27frankitoxYou can only use it in non-generated keyword nodes, right?#2023-04-0613:30borkdudeI don't think that matters#2023-04-0613:34frankitoxIf I have a generated keyword like
(def k {:k :one, :namespaced? nil, :clj-kondo.impl/generated true})
When I try retrieving the metadata I loose the location stuff
(meta k) ;; => nil
#2023-04-0613:35borkdude@U3UFFB420 you should create keywords with (api/keyword-node :foo) and enrich them with reg-keyword! (the exclamation mark is misleading) and return that keyword node from your hook#2023-04-0613:35borkdudeit won't have any metadata since you didn't attach any#2023-04-0613:36borkdudeif you want to attach a location you can re-use metadata from other nodes:
(with-meta new-node (meta old-node))
#2023-04-0613:37frankitoxI see. If I don't add the metadata I don't get the jump to definition thing working#2023-04-0613:37frankitoxthank you!#2023-04-0613:44borkdudeindeed, so it's best to re-use the location from another surrounding node or so#2023-04-0616:12fuadSomething a bit weird happening: I added https://github.com/clj-commons/potemkin/tree/master as a dep to my app and apparently it exports a clj https://github.com/clj-commons/potemkin/blob/master/resources/clj-kondo.exports/potemkin/potemkin/potemkin/namespaces.clj (called potemkin.namespaces) with the clj-kondo config. That namespace requires clj-kondo.hooks-api but does not use it. This caused my naive lint command (which simply picks up all clojure files in the current directory) to fail:
./.clj-kondo/potemkin/potemkin/potemkin/namespaces.clj:2:14: warning: namespace clj-kondo.hooks-api is required but never used
I probably should be feeding clj-kondo the only the files I have checked into git, but I'm wondering a if clj-kondo could/should ignore the .clj-kondo dir itself.
#2023-04-0616:13borkdudeYou should indeed just lint the files you want to lint, not the ones you don't want to lint :)#2023-04-0616:13borkdudeLinting still happens inside .clj-kondo since it's useful to have linting while writing hook code#2023-04-0616:14fuadAh, so there might be code in there, not just configs. That makes sense.#2023-04-2905:12Matthew Davidson (kingmob)Is there anything I can do here? The potemkin kondo hooks aren't the most sophisticated or anything#2023-04-1017:49vemvbefore I try to repro more carefully... is there any particular reason why :lint-as would not work? I still see unresolved-symbol within the defn, and unresolved var for the produced var ...I've used lint-as lots in the past, fairly sure I'm not doing sth dumb 😸 (and I cleaned the cache for good measure)#2023-04-1017:54borkdudehard to tell without an example / repro :)#2023-04-1017:55vemvsure, I was looking for something like "it has so-and-so edge case / limitation" this is a private codebase#2023-04-1017:56borkdudethe only reason that comes to mind that it might be a configuration typo#2023-04-1017:56borkdudeor the custom defn is not like the original defn syntactically#2023-04-1018:02vemv> or the custom defn is not like the original defn syntactically (edited) that was it! it was almost like a defn, except for a nuance. clj-kondo.lint-as/def-catch-all fits better than defn .#2023-04-1302:05ericdalloThere is a kondo analysis missing issue that happens a lot in Nubank projects that if fixed would help a lot developing, especially completion lsp feature 🧵#2023-04-1302:07ericdalloAfter some debugging I found it's related with the usage of schema.core/defn , when you have a map with odd pairs all analysis of that function are lost: This works, returning all keywods, var-usages and other analysis as expected, even with invalid map (common when you are writing code and completing):
(defn foo []
  (str {:a 1 :b}))
This doesn't return any analysis inside foo:
(schema.core/defn foo []
  (str {:a 1 :b}))
#2023-04-1302:08ericdalloIs quite easy to spot the issue in editor where lens, semantic tokens and other features are missing for s/defn:#2023-04-1302:13ericdalloI think this kondo only repro proves it:
clj -Sdeps '{:deps {clj-kondo {:mvn/version "2023.03.17"}}}' -m clj-kondo.main --config '{:config-paths ^:replace [] :output {:format :json :analysis {:keywords 
true}}}' --lint - <<< '(ns foo (:require [schema.core :as s])) (s/defn foo [] (str {:a 1 :b}))' |jq .
#2023-04-1307:35borkdudeok issue welcome#2023-04-1312:23ericdallothanks: https://github.com/clj-kondo/clj-kondo/issues/2048#2023-04-1309:09tobiasAny chance that in the future clj-kondo could add static analysis support for the for-by macro used in Electric Clojure? • e/for-by: a reactive map operator, stabilized to bind each child branch state (e.g. DOM element) to an entity in the collection by id (provided by userland fn - similar to React.js key). See example https://electric-examples-app.fly.dev/user.demo-system-properties!SystemProperties#2023-04-1309:10borkdude@UA9399DFZ This is something that library authors or users can do themselves in the form of hooks#2023-04-1309:11borkdudeIf you want I can guide you through that process. Then you can either contribute that back to the project or keep it as a separate dependency#2023-04-1309:37tobiasOh nice, I didn't know about hooks for extending clj-kondo. Thanks for the offer of guiding me through the process but I think I'm not the right person to take this on as don't really understand how electric works and I'm a noob at macros.#2023-04-1309:39tobias@U09K620SG is this possibly something the #C7Q9GSHFV team would consider for the future?#2023-04-1309:41borkdudeFYI @U09K620SG I'd be available in helping this#2023-04-1310:15Dustin Getzcertainly we want to include this#2023-04-1314:22nonrecursivehey y’all, I’m doing some local library development and I’m running into an issue where I’ll update a library to say, add a function, but clj-kondo isn’t recognizing that function in another project that uses the updated library. how do I resolve this?#2023-04-1314:22borkdude@U0AQ1R7FG are you using clj-kondo directly in emacs or via clojure-lsp?#2023-04-1314:23nonrecursivevia clojure-lsp#2023-04-1314:23borkdudethen it's just a matter of doing lsp-workspace-restart I think#2023-04-1314:23borkdudein the project that uses the library#2023-04-1314:25nonrecursiveoh great, thanks!#2023-04-1314:25nonrecursivethat did it. thank you!#2023-04-1317:10HachmaninowHi. Referring back to this older question: https://clojurians.slack.com/archives/CHY97NXE2/p1636046966102200 This answer was given: https://clojurians.slack.com/archives/CHY97NXE2/p1636047101103800 I tried it, but for me it does not work. I also assumed maybe there is a typo in the response and it should rather be:
{:lint-as 
 {monger.operators/$set clojure.core/def
  monger.operators/$addToSet clojure.core/def}}
? Still, it has no effect… Is it possible that clojure-lsp (with Neovim) does not respect a project-local .clj-kondo/config.edn?
#2023-04-1317:27borkdudeThis only has an effect if you lint the code again in which the vars are def-ed#2023-04-1317:27borkdudeFeel free to provide a small repro project so I can check locally#2023-04-1317:44HachmaninowAfter deleting the cache directory it works now. Thank you so much @U04V15CAJ!#2023-04-1412:08borkdude#2023-04-1521:51rschmuklerIs there any way to have a hook treat a namespace as required? I am working on writing a hook for a macro that expands into a call to clojure.core.match/match - I would like the expansion to be linted by clj-kondo - The consuming namespaces don't require clojure.core.match directly (instead the macroexpansion resolves it) causing clj-kondo to hit an :unresolved-namespace error. If the consuming namespace requires clojure.core.match everything works correctly.#2023-04-1521:52borkdudeHmm yes. this issue has come up a few times now. What you can do is this:
:config-in-call {your-ns/your-macro {:unresolved-namespace {:exclude [clojure.core.match]}}}
#2023-04-1521:53rschmuklerNice, thank you! Is there any way to apply this to metadata on the node returned from the hook instead? (ie. similar to how you can add metadata for :clj-kondo/ignore)#2023-04-1521:56borkdudecurrently not yet, but you can do this in your macro:
(defmacro my-macro
  {:clj-kondo/config '{:linters {:unresolved-namespace ...}}}
  [ ])
after linting that macro, the config applies to calls to that macro this should work in clj-kondo from a month ago
#2023-04-1521:57rschmuklerHmmm, the :config-in-call doesn't seem to be working. I will try the annotation on the macro directly. Wondering if it's because of an interaction between :analyze-call and :config-in-call#2023-04-1521:59rschmukler~The metadata annotation did work correctly, but it's worth noting that because the require didn't happen, the analysis for ~ nevermind, looks to be working#2023-04-1521:59borkdudethe annotation on the macro has the same effect as config-in-call so maybe you just made a mistake in config-in-call#2023-04-1522:00borkdudeif you look in .clj-kondo/_inlined-configs or so you will see what config it expanded to#2023-04-1522:01rschmuklerChecking the .clj-kondo/_inlined-configs - should that be a file? Trying to access it but doesn't look to exist#2023-04-1522:02borkdudeit's a directory with an edn file inside of it#2023-04-1522:02borkdudewhich contains the metadata you added to the macro in an expanded form#2023-04-1522:02borkdudeI think the dir may just be called _inlined or so#2023-04-1522:03rschmuklerThe config-in-call was me copy pasting:
:config-in-call {your-ns/your-macro {:unresolved-namespace {:exclude [clojure.core.match]}}}
Needed to be
:config-in-call {your-ns/your-macro {:linters {:unresolved-namespace {:exclude [clojure.core.match]}}}}
#2023-04-1522:03borkdudeoh right#2023-04-1522:03rschmuklerThe metadata / config-in-call works 🙂 Thank you a ton for the help#2023-04-1522:03borkdudecool, so clojure.core.match analysis also works appropriately?#2023-04-1522:03rschmuklerIt does indeed 🙂#2023-04-1522:03borkdudecool#2023-04-1522:04rschmukler
(defmacro when-match
  "Similar to `when-let` but uses match patterns for binding."
  {:clj-kondo/config '{:linters {:unresolved-namespace {:exclude [clojure.core.match]}}}}
  [bindings & body]
  (let [[pattern expr] bindings]
    `(match ~expr
       ~pattern (do ~@body)
       _# nil)))
#2023-04-1522:04rschmuklerJust a simple little thing, but pretty useful. Extra useful w/ clj-kondo linting 🥳 - Thank you again for the help and everything you do for the clojure community 🙏#2023-04-1522:05borkdudeGlad to help!#2023-04-1522:05rschmuklerAhhh! The clojure.core.match analysis actually doesn't work 😞 I had a lingering require#2023-04-1522:07rschmukler(So it's giving unresolved variable warnings as written). Any way to tricking into resolving the symbol?#2023-04-1522:09borkdudeah, that's a shame. I think we should fix this in clj-kondo, to treat an excluded namespace as if it were already required. can you post an issue about that?#2023-04-1522:09rschmuklerYep, will do!#2023-04-1522:10borkdudeI don't think there's a good workaround for it now, unless maybe you generate
(do (require 'clojure.core.match) (when-let ...))
not sure if that's going to work, I don't think it will
#2023-04-1522:11borkdudeno, that won't work#2023-04-1522:12borkdudelet's just implement the exclude fix#2023-04-1522:13rschmuklerUnfortunately it doesn't work unless the macro is called in the root of the namespace (ie. it won't work on code inside a defn)#2023-04-1522:18borkdudeyeah, I expected that#2023-04-1522:20rschmuklerhttps://github.com/clj-kondo/clj-kondo/issues/2051 Thanks again for the responses and help 🙂#2023-04-1816:15imreWhen importing configuration from libs, a merge of those configs must take place somewhere if I'm not wrong. Is the order of this merge known?#2023-04-1817:03borkdude@U08BJGV6E external configs are merged in arbitrary order, after that comes local configuration (`.clj-kondo/config.edn`), then namespace-local config#2023-04-1817:08imreThank you!#2023-04-1818:39imreIf I have my uber-great-config in a dependency and want it to override all other imported configs, is there currently a way to do that?#2023-04-1818:40imreAn idea came that we'd want a centrally managed clj-kondo base config that would live in repo A and be used by all other projects living in separate repos.#2023-04-1818:41imreso I'd need something like: all 3rd party configs < my special imported configs < local config < namespace-local config#2023-04-1910:21imreAny suggestions about this? Or is there an already established way to do something similar?#2023-04-1911:25borkdudeyou can add a :config-paths entry with shared configs#2023-04-1911:25borkdudeor add the configs to a dependency and then use clojure-lsp or --copy-configs#2023-04-1911:26borkdudethe merging order shouldn't matter since third party configs should only be concerned with specific libs#2023-04-1911:27imreThanks, I'll give it a go, then. I'm still marginally concerned that I cannot reliably override parts of a third party config but I guess it should be a rare need.#2023-04-1911:28borkdudeexplicit :config-paths has precedence over copied configs#2023-04-1911:30imreOh, so anything I name there explicitly overrides anything that's copied? Or is it if there's a config-paths entry then any other copied configs won't be considered?#2023-04-1911:34borkdudethe first#2023-04-1911:34borkdude:config-paths is basically treated like local config#2023-04-1911:34imreOh, that's excellent, then#2023-04-1911:35imreAnd I'm guessing the 'real' local config still takes precedence over those?#2023-04-1911:35borkdudeI think so, if I recall correctly#2023-04-1911:35imreCopied < config-paths < local < namespace#2023-04-1911:36imreExactly what I'm looking for#2023-04-1911:36imreThank you!#2023-04-1817:23Noah Bogartis it possible to print the current merged config? (before processing a given file)#2023-04-1817:26borkdudeI believe you can do it with this function: https://github.com/clj-kondo/clj-kondo/blob/master/API.md#clj-kondo.core/resolve-config#2023-04-1817:26Noah Bogartcool, thank you#2023-04-1817:27borkdudeyou can also just lint an empty string and then you'll get the config back in run!#2023-04-1909:56amithgeorgeHi, I asked this https://clojurians.slack.com/archives/CCY2V0U6A/p1681752705428609 in the #kaocha channel and one the responses suggested this might be something clojure-lsp or clj-kondo plugins could handle. I will repeat the ask/question Given a certain function, find all tests that directly or indirectly execute this function. The indirectly part implies that the test might execute a function A and that in turn calls function B which in turn calls the given function. Is this possible to do automatically via clj-kondo or clojure-lsp? I currently rely on clojure-lsp/Calva to manually find references and then find their references and their references, etc. till I end up at one or more tests.#2023-04-1911:39ericdalloyes, that is already possible via https://clojure-lsp.io/features/#incoming#2023-04-1911:43amithgeorgeThis is so cool! Any way to leverage this programatically? For my usecase I would want to display the leaves where the namespace ends in -test .#2023-04-1911:44ericdallothere is nothing automatic like that, would need to be a different feature, could you elaborate it with a example?#2023-04-1911:45amithgeorgeBefore I go down the route of a feature, a commenter in the other thread mentioned the possibility of clojure-lsp plugins and using them. Is this something readily available to a plugin I write for clojure-lsp?#2023-04-1911:46ericdallodepends how you use it, if using clojure-lsp analysis via the dump feature, yes, you would have all necessary analysis to implement that kind of feature#2023-04-1911:46ericdallohttps://clojure-lsp.io/api/what-is-it/#2023-04-1911:47amithgeorgeMy use case is - I want to find all the tests that directly or indirectly execute a certain function. At a bare minimum I could imagine running a command on the terminal passing in a fully qualified function name, and I get as output all the tests that I need to run.#2023-04-1911:49ericdalloLike a Find all tests that use this function feature?#2023-04-1911:49ericdallothat sounds like a interesting thing to have built-in in clojure-lsp I think#2023-04-1911:49ericdallowould like to see some examples of that to make it more real#2023-04-1911:50amithgeorge> Find all tests that use this function yes, directly or indirectly execute the function#2023-04-1911:51ericdalloI think we could offer that as a additional custom request/response, we already have that for other custom requests/responses#2023-04-1911:54amithgeorgeI tried the Show call hierarchy feature in Calva on a function I am interested in. And I got decent results. I think I may have found an issue with multimethods. Let me create a reproduction in code that I can share. This functionality does save me a lot of time. I don't have to do it manually anymore 👍#2023-04-1911:56ericdalloah probably has some corner cases with defmethods, feel free to open a detailed issue about it, it's one of the coolest features I did in clojure-lsp IMO :)#2023-04-1918:47Sam RitchieDoes anyone here use kondo with github actions, and have some way to lint dependencies? I am seeing lots of unresolved symbol errors in my project that depends on Emmy:
(animated_drawings) [sritchie@wintermute ~/code/clj/emmy-viewers (sritchie/publish)]$ bb lint
dev/examples/functions.clj:42:5: error: Unresolved symbol: +
dev/examples/functions.clj:42:8: error: Unresolved symbol: square
dev/examples/functions.clj:43:8: error: Unresolved symbol: cube
this goes away after linting deps. I’m fine adding that step I just haven’t had to do it before
#2023-04-1918:48borkdudeThis is probably caused by :refer :all . clj-kondo can't know where these symbols come from unless you also lint that namespace#2023-04-1918:48Sam Ritchiechanging my lint action to
lint
{:doc "Lint the src and dev directories with clj-kondo."
   :task (exec 'clj-kondo.core/exec)
   :exec-args {:dependencies true
               :lint ["src" "dev"]}}
fixed it without adding any real time
#2023-04-1918:49Sam Ritchiethat is kind of wild…#2023-04-1918:49Sam Ritchieoh actually it doesn’t fix it, it suppresses all errors
(animated_drawings) [sritchie@wintermute ~/code/clj/emmy-viewers (sritchie/publish)]$ bb lint
linting took 153ms, errors: 0, warnings: 0
#2023-04-1918:49borkdudewhen linting dependencies, you should provide clj-kondo a classpath#2023-04-1918:50Sam Ritchie#2023-04-1918:50Sam Ritchieeven when I add an explicit nonsense symbol#2023-04-1918:50borkdudesee the README.md of clj-kondo#2023-04-1918:50Sam Ritchiefor sure, I was just trying to figure out how to do it within my bb.edn#2023-04-1918:50borkdudeyou need to call clj-kondo twice#2023-04-1918:51borkdudeonce with the deps and then with your own sources#2023-04-1918:51Sam RitchieI had been trying to avoid installing the clj-kondo binary, and sticking with the bb version, but I think I will copy your style here https://github.com/clj-kondo/clj-kondo/blob/master/.github/workflows/clj-kondo.yml#2023-04-1918:53borkdudeyou can do this with the bb version:
(clj-kondo/run! {:lint [(with-out-str (babashka.tasks/clojure "-Spath"))] :dependencies true)
#2023-04-1918:55borkdudeif you do that first, before your current call, all should be good#2023-04-1918:56Sam Ritchie
lint-deps
{:doc "Lint dependencies with clj-kondo."
   :task (exec 'clj-kondo.core/exec)
   :exec-args {#_#_:dependencies true
               :lint [(with-out-str
                        (babashka.tasks/clojure "-Spath"))]}}
#2023-04-1918:56Sam Ritchieman, if I have that dependencies true in there I get a success, but if I comment it out I see
(animated_drawings) [sritchie@wintermute ~/code/clj/emmy-viewers (sritchie/publish)]$ bb lint-deps
(with-out-str (babashka.tasks/clojure "-Spath")):0:0: error: file does not exist
#2023-04-1918:57borkdudehmm, is :exec-args maybe not evaluated, that could be a bug#2023-04-1918:57Sam Ritchieah, seems like it#2023-04-1918:58borkdudefor now you can write a .clj or .bb file and then call that file from bb tasks#2023-04-1918:59Sam Ritchie
name: Linter

on:
  pull_request:
  push:
    branches: [main]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v2

    - uses: DeLaGuardo/clojure-lint-action@master
      with:
        clj-kondo-args: --dependencies --lint "$(clojure -A:nextjournal/clerk -Spath)"
        github_token: ${{ secrets.GITHUB_TOKEN }}

    - uses: DeLaGuardo/clojure-lint-action@master
      with:
        clj-kondo-args: --lint src test --config '{:output {:pattern "::{{level}} file={{filename}},line={{row}},col={{col}}::{{message}}"}}'
        github_token: ${{ secrets.GITHUB_TOKEN }}
#2023-04-1918:59Sam Ritchietrying this action for now#2023-04-1918:59borkdudeyeah ok, I think that action is quite old, I'd just use setup-clojure instead which can install bb and clj-kondo#2023-04-1919:00borkdudeofficially -Spath should come before -A:foo:bar#2023-04-1919:08Sam Ritchiesorry to keep bothering you here but how weird is this… https://github.com/mentat-collective/emmy-viewers/actions/runs/4746965728/jobs/8431269901?pr=22#2023-04-1919:09Sam RitchieI don’t call clojure.core/array anywhere and I don’t get that error locally, but it fails remotely#2023-04-1919:09Sam Ritchiewith, unfortunately, no info about where it comes from#2023-04-1919:10borkdudeweird, never seen that before#2023-04-1919:10borkdudeit doesn't look like the output from clj-kondo#2023-04-1919:11borkdudecan you upgrade to the newest clj-kondo? maybe it helps#2023-04-1919:12Sam Ritchiethe output made it look like I was up to speed already…
- name: Install tools
        uses: DeLaGuardo/setup-clojure@master
        with:
          cli: latest
          bb: latest
          clj-kondo: latest
#2023-04-1919:13Sam Ritchiethat is how I did it#2023-04-1919:13Sam Ritchiemaybe a setup-clojure bug…#2023-04-1919:13Sam Ritchieseems unlikely with the error position. obviously I’m flailing here#2023-04-1919:14borkdude
Successfully installed pod clj-kondo/clj-kondo (2023.01.20)
#2023-04-1919:14borkdudepod != installed clj-kondo version#2023-04-1919:14Sam Ritchie#2023-04-1919:14Sam Ritchieah, maybe a version mismatch#2023-04-1919:15borkdudewhen you're using the pod, you don't need to externally install clj-kondo. either use the pod, or the externally installed clj-kondo#2023-04-1919:15borkdudethe two don't relate to each other#2023-04-1919:15Sam RitchieI wanted to avoid for now adding that new bb file, and simply populate the cache#2023-04-1919:16Sam Ritchieand then back out this actions change later#2023-04-1919:16borkdudeyou can also write the call to clj-kondo/exec manually, without :exec-args#2023-04-1919:17borkdude
:requires [clj-kondo.core]
:task (do (clj-kondo/run! {:lint [...] :dependencies true)
          (clj-kondo/exec {:lint ["src" "dev"]})
#2023-04-1919:17Sam Ritchiethat error even appears when I take bb out of the mix and do all clj-kondo#2023-04-1919:18borkdudeif you can repro this using the latest version, I'm all ears#2023-04-1919:19Sam RitchieI’ll work on it! I can only repro it on the github actions env#2023-04-1919:29borkdude@U017QJZ9M7W could it be related to this?
user=> clojure.core/array
Syntax error (IllegalStateException) compiling at (REPL:0:0).
var: clojure.core/array is not public
#2023-04-1919:30borkdudeperhaps you have a .cljc file in which you use array not inside a reader conditional?#2023-04-1919:33Sam Ritchie#2023-04-1919:33Sam Ritchielooks like I have a cljs file where I use array#2023-04-1919:34Sam Ritchiehttps://github.com/mentat-collective/emmy-viewers/blob/main/dev/examples/simulation/phase_portrait.cljc#L309-L312#2023-04-1919:34Sam Ritchiedefinitely suspicious#2023-04-2020:10borkdude@U017QJZ9M7W Did you manage to sort things out?#2023-04-2020:14Sam Ritchieyeah! thanks again for your help… I went with a separate bb lint-deps https://github.com/mentat-collective/emmy-viewers/blob/main/bb.edn#L54-L66 and then a separate step in the action: https://github.com/mentat-collective/emmy-viewers/blob/main/.github/workflows/kondo.yml#L27-L31#2023-04-2111:53borkdudebtw I found something that enables you to evaluate the exec-args:
$ bb -e "(babashka.tasks/exec 'clojure.core/prn {:exec-args {:a (+ 1 2 3)}})" --x
{:a 6, :x true}
#2023-04-2111:53borkdudeI think it makes sense to keep the :exec-args key in tasks static so it's the same as deps.edn and reserve the above (exec ...) call for evaluated exec args#2023-04-2111:54borkdudeI'll document this in the book#2023-04-2111:55borkdudebtw you went to the European Lisp Symposium last year right? This year it's close to my city, I'm on the fence of going or not.#2023-04-2115:33Sam Ritchieit has the feel of a common lisp meetup with lots of good energy, the papers and talks are an excuse for everyone to get together… maybe that is every conference?? it ended up being maybe 30-40 people last year, not that big#2023-04-2115:35borkduderight#2023-04-1920:33Noah Bogartis this a bug?
$ echo "(assoc {})" | clj-kondo --lint - 
linting took 6ms, errors: 0, warnings: 0
#2023-04-1920:34borkdudeissue welcome#2023-04-1920:34Noah Bogartcool, will do#2023-04-1920:36borkdudeno wait.#2023-04-1920:36borkdude
$ echo "(assoc {})" | clj-kondo --lint -
<stdin>:1:1: error: clojure.core/assoc is called with 1 arg but expects 3 or more
linting took 26ms, errors: 1, warnings: 0
#2023-04-1920:36borkdudenot sure what version you are using#2023-04-1920:36Noah Bogartuh oh, maybe i broke something#2023-04-1920:37Noah Bogarti deleted my config file to make sure it wasn't used, but deleting the cache shows that there was a mistake somewhere. sorry for the false alarm#2023-04-2019:39genmeblogIs the :exclude-patterns planned in :unused-private-var linter?#2023-04-2019:43borkdudeDo you have that many private vars that you need to suppress a whole lot of them? :)#2023-04-2019:43genmeblogYes! :)#2023-04-2019:44borkdudeTell me more, I want to see them :)#2023-04-2019:44borkdudebut seriously, I think that would be fine#2023-04-2019:44borkdudeissue / PR welcome#2023-04-2019:45genmebloghaha, it's not easy to convince you 🙂#2023-04-2019:46genmeblogI use some general patterns for private functions to later generate public functions#2023-04-2019:46borkdudeThe way I usually solve this is move those to an foo.internal namespace and make them public#2023-04-2019:48genmebloghmmm... it's possible in this case.#2023-04-2019:49genmeblogactually I can make them public#2023-04-2019:50genmebloganyway, I think that every linter which can have :exclude could have :exclude-patterns as well, what do you think?#2023-04-2019:50genmeblogit will enable a lot of possiblities and simplification in some cases#2023-04-2020:07borkdudeyes, I'm not opposed to it#2023-04-2020:09genmeblogI'll leave the issue then#2023-04-2020:34borkdude@U1EP3BZ3Q Note that you can also disable the unused-private-var linter in one specific namespace only#2023-04-2020:36genmeblogYes, I know it. I usually prefer to narrow exclusion as much as possible. I solved this particular case by making these functions public.#2023-04-2020:34genmeblogAnother question today, amap warns about unused binding ret or any used symbol (there was an issue about throwing the error which was fixed). Is it ok and should I change it to _ret for example?#2023-04-2020:35borkdudeDo you have an example?#2023-04-2020:37genmeblogThe example from ClojureDocs (https://clojuredocs.org/clojure.core/amap)#2023-04-2020:38genmeblog#2023-04-2020:38genmeblog
(def an-array (int-array 25000 (int 0)))

(time (amap ^ints an-array 
            idx 
            ret 
            (+ (int 1) 
               (aget ^ints an-array idx))))
#2023-04-2020:40genmeblogclj-kondo v2023.04.14#2023-04-2020:42borkdudeyes, underscore seems fine there if ret is not used?#2023-04-2020:42borkdudeor am I missing something?#2023-04-2020:43genmeblogret is internal name used by amap which is a macro. It expands as:
(let*
  [a__6552__auto__
   an-array
   l__6553__auto__
   (alength a__6552__auto__)
   ret
   (aclone a__6552__auto__)]
  (loop*
    [idx 0]
    (if (< idx l__6553__auto__)
      (do
        (aset ret idx (+ (int 1) (aget an-array idx)))
        (recur (unchecked-inc idx)))
      ret)))
#2023-04-2020:44genmeblogIn 99% you do not use this name.#2023-04-2020:44borkdudewhy does amap make you choose a name for this?#2023-04-2020:45genmeblogIt doesn't. But this is stated in documentation >
Maps an expression across an array a, using an index named idx, and
> return value named ret, initialized to a clone of a, then setting 
> each element of ret to the evaluation of expr, returning the new 
> array ret.
#2023-04-2020:45genmeblogSo probably everyone just leave it as ret#2023-04-2020:45borkdudeyou can also name it _#2023-04-2020:46genmeblogOf course.#2023-04-2020:46borkdudeI'm fine with suppressing that lint warning#2023-04-2020:47borkdudeit raises the question: is there ever a situation when someone does want to have a warning about that being unused? seems unlikely right#2023-04-2020:49genmeblogSeem unlikely I think. It's kind of pattern introduced by authors and documented as "use ret"#2023-04-2020:49genmeblogareduce is another case#2023-04-2020:49borkdudesure issue welcome, although myself I've always just underscored the binding#2023-04-2020:54genmeblogWithout knowing the internals, most people - probably - will use ret because it's stated in the doc and clojuredocs examples. I agree that maybe there is someone who will complain about switching off this warning, who knows... Anyway, leaving the issue.#2023-04-2020:57genmeblogareduce is the wrong example, so it applies only for amap#2023-04-2020:58genmeblogret in areduce is and should be used by user (it's the accumulator)#2023-04-2021:00borkdudeit feels a bit arbitrary to make an exception just for amap - I think most clj-kondo users will know that when you're not referring to ret, they can underscore it#2023-04-2021:09genmeblogYes, it's arbitrary. I agree with that. Well. I've never hit the case when ret was referred. But it should be named.#2023-04-2021:09genmeblogI'm starting to have doubts 🙂#2023-04-2107:01Chris McCormickI've just upgraded clj-kondo and I am seeing "Namespace name does not match file name". My file is src/joplinsite/plugin.cljs and my ns is (ns joplinsite.plugin...) . I am sure I have missed something here, but a search for this error on the GitHub and in this chat did not yield much. Any ideas?#2023-04-2107:02borkdudeThe three dots might be the problem?#2023-04-2107:05Chris McCormickSorry that's just meant to indicate there is more stuff in there. The full ns as a (:require ...) next (with the three dots here meaning "more stuff").#2023-04-2107:05Chris McCormickFull ns:
(ns joplinsite.plugin
  (:require
    [clojure.data :refer [diff]]
    [applied-science.js-interop :as j]
    [promesa.core :as p]
    [shadow.resource :as rc]
    [clojure.string :refer [join]]
    [reagent.core :as r]
    [reagent.dom :as rdom]
    [reagent.dom.server :refer [render-to-static-markup]]
    ["crypto-js/sha512" :as sha512]
    ["crypto-js/enc-hex" :as enc-hex]
    ["crypto-js" :as crypto-js]))
#2023-04-2107:11borkdudeCan you make something I can clone locally? I’ll check in an hour or so#2023-04-2107:11Chris McCormickOk will do, thanks.#2023-04-2107:13Chris McCormickI can temporarily turn off the warning as per instructions on the original PR, so no urgency to fix it, but I will create a repro now + ticket.#2023-04-2107:35Chris McCormickhttps://github.com/clj-kondo/clj-kondo/issues/2055 zipfile containing a small repro is attached.#2023-04-2108:01Chris McCormickFixed with an upgrade of ALE, thanks!#2023-04-2108:03borkdudecool!#2023-04-2214:57borkdudeI sometimes I have ideas for fun projects but not always time to realize them. One of those fun projects that has been in the back of my mind is creating a code visualizer like the Github UI. When you view code in the Github UI you can click on things for navigation and see cross references. I want to make a similar thing for clojure code but then based on clj-kondo analysis. Would it be useful? I don't know? Fun? Maybe. Does it take time? Yes, but maybe not that much. If you have thoughts on this, please respond in thread.#2023-04-2217:29lispycloudsOne way to reduce some work is to use SourceGraph’a SCIP: https://about.sourcegraph.com/blog/announcing-scip The project could be to convert kondo’s analysis to SCIP and SourceGraph takes care of the rest: visualise, nav etc. I can ask TJ from nvim core who works there to help merge it up stream, probably could be a part of https://github.com/sourcegraph/scip-java like kotlin/scala? What do you think?#2023-04-2405:28Ben SlessYou mean something like https://github.com/jpmonettas/clograms/ ? I have general interest in something like this, with an added bonus of loading it from inside a running process and having different front ends for it Emacs, Clerk, Portal, Membrane I'm interested in how this can enhance the repl experience#2023-04-2407:33phronmophobicI'm also interested in a similar idea. It's part of the reason behind dewey. Not only can you jump to source, you could look up usages/references across github (or other open source repositories that get indexed in the future).#2023-04-2407:36borkdudeI didn't mean something like clograms or SCIP: basically just the Github code UI but powered by clj-kondo analysis for better navigation/references that what Github currently has.#2023-04-2407:36borkdudeI'd prefer to just have static HTML that you could serve as part of your Github pages#2023-04-2408:38p-himikTrying to write a hook for dom-top.core/loopr which is like which is like loop + kinda for + finally. Started with this:
(defn loopr [{:keys [node]}]
      (println "loopr hook")
      (let [[_ acc-vec binding-vec & body] (:children node)
            _ (prn acc-vec binding-vec)
            new-node (api/list-node
                       (list*
                         (api/token-node 'loop)
                         (api/vector-node acc-vec)
                         (api/list-node
                           (list*
                             (api/token-node 'let)
                             (api/vector-node binding-vec)
                             body))))]
           {:node new-node}))
Clj-kondo docs on hooks state in a similar situation: "Moreover, it will report unused bindings and will give warnings customized to this macro." But I don't see it being the case here. Perhaps related, but I see another issue: Can't parse /home/p-himik/dev/git/ensemble/src/test.clj, Key must be integer pointing at the very first character in this file:
(ns test
  (:require [dom-top.core :as dom-top]))

(dom-top/loopr [acc []]
               [x (repeat 10 (range 10))
                y x]
               (recur (conj acc (inc y)))
               (apply + acc))
Not sure how to debug the above and what the mentioned key is supposed to be. Apart from that, (binding [api/*reload* true] ...) doesn't seem to work for me for some reason. If I replace the first println message above with something else and re-execute (pprint/pprint (binding [api/*reload* true] (:findings (clj-kondo/run! {:lint ["/home/p-himik/dev/git/ensemble/src/test.clj"]})))), it prints the old message. Any advice?
#2023-04-2408:43borkdudecan you maybe try to lint that code from the command line? this should not have any reloading problems#2023-04-2408:43borkdude"Key must be integer" seems to be some kind of type error, where you are accessing something in a vector using a non-integer?#2023-04-2408:44borkdudeAre you using the most recent clj-kondo?#2023-04-2409:07p-himikYeah, "LATEST" just from today. Hmm, the CLI doesn't given that error at all. Aaaand the "key must be integer" error is gone after restarting the REPL, even though I have changed no files.#2023-04-2409:09borkdudeMaybe the *reload* thing isn't working properly then. It's used here: https://github.com/clj-kondo/clj-kondo/blob/a284300c3ed0c0c201d3d4933d22323ed44bd2d1/src/clj_kondo/impl/hooks.clj#L115#2023-04-2409:10p-himikAh, hold on - I did change something, just didn't register it in my memory because my wife called me for breakfast that exact instant. :D Alright, the error is back. So seems like it's in the hook code and maybe I can simply try-catch it.#2023-04-2409:33p-himikFound my mistake - I was wrapping nodes into other nodes. Is there a way to unparse a node? Can't find it in the code or the docs. Just printing it gives me
<list: (loop [acc []] [:tag :list] [:format-string (%s)] [:wrap-length 2] [:seq-fn #object[clj_kondo.impl.rewrite_clj.node.seq$list_node$fn__1159 0x7be299ec clj_kondo.impl.rewrite_clj.node.seq$list_node$fn__1159@7be299ec]] [:children (<token: let> <vector: [x (repeat 10 (range 10)) y x z x]> <list: (recur (conj acc (inc y)))>)] [:clj-kondo.impl/generated true])>
and I have no idea what's wrong because recur is clearly there but the linter says that I'm using loop without recur now. I see api/pprint but judging by the code it will simply pretty-print the above. And also it's not available via the CLI tool for some reason: WARNING: error while trying to read hook for dom-top.core/loopr: Could not resolve symbol: api/pprint where api is [clj-kondo.hooks-api :as api].
#2023-04-2409:33borkdudeWhat do you mean with "unparse a node"#2023-04-2409:34p-himikTo turn it into a string with Clojure code that I've "rewritten".#2023-04-2409:34borkdudeThis:
[:tag :list] [:format-string (%s)] 
seems like you're nesting a node wrong, it's likely that you passed a node into a list-node or so while you should pass a vector with that node inside of it
#2023-04-2409:34borkdudeyes, you can call str on it#2023-04-2409:38p-himikAh, str was also returning those internal vectors so I assumed that it wasn't the way to get the code. I see now, I was using list* where I should've been using list. Thanks!#2023-04-2409:41borkdudeMaybe I should do some verification when constructing those things, it trips me up sometimes too#2023-04-2409:41borkdudeFeel free to post an issue about that#2023-04-2409:48p-himikDone: https://github.com/clj-kondo/clj-kondo/issues/2056#2023-04-2409:56borkdudeThanks!#2023-04-2409:51p-himikAnother issue that I'm not sure how to approach given my limited exposure to all the related things. After plugging clj-kondo into Cursive via the LSP plugin, typing now causes the code to flash with errors. E.g. I'll be typing in the binding vector of a let form and upon any new character the whole let form is highlighted in red for a single frame, along with some other completely unrelated parts of the code. No clue what to blame here - the linter, the LSP plugin, maybe Cursive, maybe some unset settings,...#2023-04-2409:54p-himikThis is what I mean.#2023-04-2409:58borkdude@U2FRKM4TW Perhaps you can try #C02UN1B0998 for Cursive? The lsp plugin isn't maintained anymore for a while I believe, but I could be wrong.#2023-04-2409:58borkdudeI mean the intellij lsp plugin, the clj-kondo lsp server is still maintained#2023-04-2410:00p-himikAh, crap. I'm willfully stuck with an older version of IDEA that that extras plugin doesn't support. I guess that brings the "I'll move to Calva any day now" moment closer. :D#2023-04-2410:01borkdude@U2FRKM4TW I think the IDEA version is just a string in that clj-extras thing, perhaps you can compile it yourself...#2023-04-2410:02borkdudemoving to Calva will bring you the full clojure-lsp support (based on clj-kondo analysis ) which is quite good now, only the Java interop stuff is subpar compared to IDEA#2023-04-2410:02borkdude(but we're working on that)#2023-04-2410:05borkdudefor the flashy thing while typing the binding name: it might be caused by this, I don't see this while typing this in emacs, I only get a warning on the vector that the bindings aren't even#2023-04-2410:07borkdudeWell, other things are warned about then too: since the bindings and values are now swapped basically, the syntactic check that a binding name should be a symbol messes things up#2023-04-2410:27p-himik> (but we're working on that) Sweet! That's one of those things that I definitely value in IDEA. Being able to seamlessly navigate between CLJ an Java code is a blessing.#2023-04-2414:19genmeblogSOLVED: remind to myself, do precisely as it states in the docs... I have a problem with importing configs from external library. Probably doing something wrong here. The library's config (it's on the Clojars, and jar includes these files): https://github.com/Clojure2D/clojure2d/tree/master/resources/clj-kondo.exports/clojure2d/clojure2d My local project's deps.edn content:
{:paths ["src"]
 :deps {org.clojure/clojure {:mvn/version "1.11.1"}
        clojure2d/clojure2d {:mvn/version "1.4.5-SNAPSHOT"}}}
Calling the following doesn't copy configs:
$ clj-kondo --lint "$(clojure -Spath)" --copy-configs --skip-lint
No configs copied.
linting took 75ms, errors: 0, warnings: 0
Any idea what's wrong?
#2023-04-2414:20borkdudecheck if the files are really in the jar file#2023-04-2414:21borkdudealso you need to have a .clj-kondo directory#2023-04-2414:21borkdudein the project where you are copying the configs#2023-04-2414:25genmeblogomg... ok... It's working...#2023-04-2414:25genmeblogI've made testing repo without .clj-kondo#2023-04-2414:26genmeblogBut in the other (already existing, with .clj-kondo) repo I skipped --lint arg.#2023-04-2414:26borkdudecool :)#2023-04-2509:13witekI have a REPL with clj-kondo inside. How can I start linting in background (like watch) and get analysis data whenever it is updated?#2023-04-2509:15borkdudeYou know how to do this in general, without the watch?#2023-04-2509:19witekNot realy. I found clj-kondo.core/run!. But it does not provide analysis data.#2023-04-2509:21borkdude
(-> (clj-kondo/run! {:lint ["src"] :config {:analysis true}})
 :analysis)
#2023-04-2509:24witekYeah. That works. What about the watch? Will I have to implement this myself? Or is there something in clj-kondo that I can reuse?#2023-04-2509:24borkdudeImplement yourself. I think you could use nextjournal/beholder for this#2023-04-2515:40ThierryQuestion about hooks and lint-as. I have this hook for taoensso.timbre/refer-timbre so each fn exists in the namespace it is used in. This overcomes the unresolved symbol errors.
(ns hooks.taoensso.timbre
  (:require [clj-kondo.hooks-api :as api]))

(defn only-args [name-symbol]
  (api/list-node
   [(api/token-node 'defn) (api/token-node name-symbol) (api/vector-node [(api/token-node '&) (api/token-node '_)])]))

(defn refer-timbre [{:keys [node]}]
      (let [new-node (api/list-node (into [] (concat (api/token-node 'do)
                                                     (map only-args
                                                          ['trace  'debug  'info  'warn  'error  'fatal  'report
                                                           'tracef 'debugf 'infof 'warnf 'errorf 'fatalf 'reportf]))))]
           {:node new-node}))
So far so good. But these fns do not get linted so I added them to :lint-as like so:
taoensso.timbre/tracef clojure.core/format
           taoensso.timbre/debugf clojure.core/format
           taoensso.timbre/infof clojure.core/format
           taoensso.timbre/warnf clojure.core/format
           taoensso.timbre/errorf clojure.core/format
           taoensso.timbre/reportf clojure.core/format
This works, but only if the fn is called with full namespace or required :as namespace. The refer-timbre fns do not get linted. I tried solving this by updating the refer-timbre hook by adding the linter type inline, but doesnt work. Any tips?
(defn refer-timbre [{:keys [ns node]}]
  (let [new-node (api/list-node (into [] (concat (api/token-node 'do)
                                                 (map only-args
                                                      ['trace  'debug  'info  'warn  'error  'fatal  'report
                                                       'tracef 'debugf 'infof 'warnf 'errorf 'fatalf 'reportf]))))
        lint-as-str-map (reduce (fn [m f]
                                   (let [full-name (symbol (str 'ns "/" f))]
                                     (assoc m full-name 'clojure.core/str)))
                                 {}
                                 ['trace  'debug  'info  'warn  'error  'fatal  'report])
        lint-as-frmt-map (reduce (fn [m f]
                                   (let [full-name (symbol (str 'ns "/" f))]
                                     (assoc m full-name 'clojure.core/format)))
                                 {}
                                 ['tracef 'debugf 'infof 'warnf 'errorf 'fatalf 'reportf])]
    {:node new-node
     :lint-as (merge lint-as-str-map lint-as-frmt-map)}))
#2023-04-2515:43borkdude@U02CX2V8PJN is refer-timbre a user-level function or an implementation detail of timbre?#2023-04-2515:43borkdudeimo the usage of refer-timbre isn't worth it compared to just :refer [...]#2023-04-2515:44borkdudeor :as timbre#2023-04-2515:44Thierryrefer-timbre is an implementation detail of timbre: https://github.com/ptaoussanis/timbre/blob/4b421a36fe2288abbcd58eb6d3e44f08b96b1357/src/taoensso/timbre.cljc#L969-L980#2023-04-2515:45ThierryThe hook adds the fn to each namespace so its not flagged as unresolved
#2023-04-2515:45borkdudeso the only reason you are configuring it is because of unresolved symbols?#2023-04-2515:45borkdudeyou can also :unresolved-symbol :exclude them#2023-04-2515:45borkdudeor the entire namespace#2023-04-2515:46ThierryIf you look at it that way, then yes. But disabling :unresolved-symbol config would be global#2023-04-2515:46Thierryrefer-timbre is used in almost every namespace of this project#2023-04-2515:46Thierryhence the hook (i didnt write it btw)#2023-04-2515:46borkdudeWhat does your refer-timbre hook expand into? Can you add a (println node) inside of it and then print the expansion by linting on the command line?#2023-04-2515:47ThierryAh I have been experimenting#2023-04-2515:47borkdude> But disabling :unresolved-symbol config would be global You can exclude only one namespace#2023-04-2515:47Thierryhold on#2023-04-2515:47Thierrywait thats kinda larg#2023-04-2515:48Thierrylet me fix that#2023-04-2515:48Thierryhttps://gist.github.com/LouDnl/94f563fd3a6b5288aea4ed4e422e723d#2023-04-2515:52borkdudeCan you print (str node)?#2023-04-2515:53Thierrylike this?
"([:value do] [:string-value \"do\"] [:clj-kondo.impl/generated true] (defn trace [& _]) (defn debug [& _]) (defn info [& _]) (defn warn [& _]) (defn error [& _]) (defn fatal [& _]) (defn report [& _]) (defn tracef [& _]) (defn debugf [& _]) (defn infof [& _]) (defn warnf [& _]) (defn errorf [& _]) (defn fatalf [& _]) (defn reportf [& _]))"
#2023-04-2515:53borkdudeyes, it seems this node isn't correct#2023-04-2515:53borkdudeyou should just see an s-expression when you print it like this#2023-04-2515:53borkdudethe node with do gets pulled apart#2023-04-2515:54Thierrymaybe because I am doing it in a repl? I do it like this:
(binding [api/*reload* true]
           (load-file ".clj-kondo/hooks/taoensso/timbre.clj")
           (str (:node (hooks.taoensso.timbre/refer-timbre {:node (api/parse-string "(taoensso.timbre/refer-timbre)")})))
#2023-04-2515:57ThierryI added a (prn (str node)) and (prn (str new-node)) to the hook. This is the output:
"(taoensso.timbre/refer-timbre)"
"([:value do] [:string-value \"do\"] [:clj-kondo.impl/generated true] (defn trace [& _]) (defn debug [& _]) (defn info [& _]) (defn warn [& _]) (defn error [& _]) (defn fatal [& _]) (defn report [& _]) (defn tracef [& _]) (defn debugf [& _]) (defn infof [& _]) (defn warnf [& _]) (defn errorf [& _]) (defn fatalf [& _]) (defn reportf [& _]))"
#2023-04-2515:57borkdudesorry, this is a bit too much for me, can you just make a github repo that I could clone locally and look at?#2023-04-2515:57Thierryumm yea sure, will do that and ping you here#2023-04-2515:58borkdude👍#2023-04-2515:58borkdudeit's easier to find the mistake and point out where it is that way#2023-04-2517:45Thierry@U04V15CAJ https://github.com/LouDnl/timbrehook#2023-04-2517:48borkdude@U02CX2V8PJN One of the issues is (concat node some-list)#2023-04-2517:48borkdudeyou should use cons there to prepend a single item to a list#2023-04-2517:50borkdudeThe other issue is, your hook generates:
"(do (defn trace [& _]) (defn debug [& _]) (defn info [& _]) (defn warn [& _]) (defn error [& _]) (defn fatal [& _]) (defn report [& _]) (defn tracef [& _]) (defn debugf [& _]) (defn infof [& _]) (defn warnf [& _]) (defn errorf [& _]) (defn fatalf [& _]) (defn reportf [& _]))
Why not generate:
(require '[taoensso.timbre :refer [trace]])
etc
#2023-04-2517:50borkdudegotta go now, will look at replies later#2023-04-2517:51Thierrygood point, I will look into that. like I said, I didn't create the hook in the project. thanks so far!#2023-04-2517:51borkdudeoh right, who did then?#2023-04-2517:51ThierryI dont know, it was already in the project I maintain. Ill see if I can find it in the git history#2023-04-2517:53borkdudeok, I think it makes more sense to use :hooks {:macroexpand ... and then just copy paste the macro there, so it expands into a require#2023-04-2517:53borkdudelaterz#2023-04-2612:11ThierryHave tried some stuff but end up with undefined errors every time. Add the fns to the regular refer line solves it, but that would mean a change to each namespace and makes the refer-timbre fn useless because its meant to overcome such refers#2023-04-2612:13borkdudeWhy don't you expand the hook into
(require '[taoensso.timbre :refer [...]])
This should work
#2023-04-2612:13borkdudesince that is exactly what this macro does#2023-04-2612:14ThierryI think I tried that yesterday but didnt solve anything. It worked, but still no linting on the referred fns. Will have another look later today#2023-04-2612:15borkdudePlease try this and then push to the repro repo, then I'll have another look#2023-04-2616:02ThierryI pushed the change: https://github.com/LouDnl/timbrehook#2023-04-2617:10borkdudeok, looking :)#2023-04-2617:12borkdude@U02CX2V8PJN You're not supposed to use this namespace:
[clj-kondo.impl.rewrite-clj.node :as node]
impl means "internal, implementation detail" Instead of quote-node you can just write (list-node [(token-node 'quote) ...])
#2023-04-2617:14borkdudelike this:
(defn refer-timbre [_]
  (let [fns      ['trace  'debug  'info  'warn  'error  'fatal  'report
                  'tracef 'debugf 'infof 'warnf 'errorf 'fatalf 'reportf]
        new-node (api/list-node
                  [(api/token-node 'require)
                   (api/list-node
                    [(api/token-node 'quote)
                     (api/vector-node
                      [(api/token-node 'taoensso.timbre)
                       (api/keyword-node ':refer)
                       (api/vector-node
                        (mapv api/token-node
                              fns))])])])]
    {:node new-node}))
#2023-04-2617:20borkdudeI think this does the trick completely:
(defn refer-timbre [_]
  (let [fns      ['trace  'debug  'info  'warn  'error  'fatal  'report
                  'tracef 'debugf 'infof 'warnf 'errorf 'fatalf 'reportf]
        new-node (api/list-node
                  [(api/token-node 'require)
                   (api/list-node
                    [(api/token-node 'quote)
                     (api/vector-node
                      [(api/token-node 'taoensso.timbre)
                       (api/keyword-node ':refer)
                       (api/vector-node
                        (mapv api/token-node
                              fns))])])])]
    {:node (with-meta new-node
             {:clj-kondo/ignore [:duplicate-require :unused-referred-var]})}))
#2023-04-2617:20borkdudeIt ignores some warnings about duplicate requires and unused referred vars#2023-04-2617:43ThierryIndeed it does, thank you very much!#2023-04-2617:44borkdudeI think it could be worth adding this configuration to timbre itself btw#2023-04-2617:47ThierryAfter applying it to the project it immediately identified some errors 🙂#2023-04-2617:50borkdudecool :)#2023-04-2519:34dpsuttonanyone know why this is still being reported as an error?
(t2/define-before-insert ::created-at-timestamp
  [instance]
  #_{:clj-kondo/ignore [:private-call]}
  (#'mi/add-created-at-timestamp instance))
> add-created-at-timestamp is private [private-call]
#2023-04-2519:35dpsutton#2023-04-2520:23borkdudeThis should be fixed in the latest release, issue 2043: https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#20230414#2023-04-2810:45borkdudeIf you are at the conj or are watching the live stream, there's going to be a talk by @ericdallo from #CPABC1H61 there today, first thing.#2023-04-2908:49Matthew Davidson (kingmob)I'm weighing options for linting the two main macros used to define every operator in primitive-math (variadic-proxy and variadic-predicate-proxy). I like kondo a lot, but it seems like we have many options when it comes to macro linting, and no guide. I could use a flowchart 😉 I originally thought I could use the macros as their own hooks, but then I wondered if :lint-as def or declare would be better, since I mostly just want the various operators to be resolved. Linting as def works, but using def doesn't turn up an error if the operators are used as higher-order fns, which it should, since they're macros. Thoughts?#2023-04-2908:57Matthew Davidson (kingmob)One catch is, they're macro-generating macros.#2023-04-2909:00borkdudeLet's start with an example. What often only matters is how the code is used superficially, not what the macros generate in real life#2023-04-2909:01Matthew Davidson (kingmob)Sure, here's varidic-proxy:
(defmacro ^:private variadic-proxy
  "Creates left-associative variadic forms for any operator."
  ([name fn]
     `(variadic-proxy ~name ~fn ~(str "A primitive macro version of `" name "`")))
  ([name fn doc]
     `(variadic-proxy ~name ~fn ~doc identity))
  ([name fn doc single-arg-form]
     (let [x-sym (gensym "x")]
       `(defmacro ~name
          ~doc
          {:arglists '([~'x] [~'x ~'y] [~'x ~'y & ~'rest])}
          ([~x-sym]
             ~((eval single-arg-form) x-sym))
          ([x# y#]
             (list '~fn x# y#))
          ([x# y# ~'& rest#]
             (list* '~name (list '~name x# y#) rest#))))))
#2023-04-2909:02Matthew Davidson (kingmob)(I tried dropping it in as a :macroexpand hook, and removeing the ^:private, but it doesn't seem to be working...)#2023-04-2909:02borkdudeSo you want support for this macro for yourself, not for third party users, am I right?#2023-04-2909:02borkdude(since it's private)#2023-04-2909:03Matthew Davidson (kingmob)Mostly for users, because it defines all the public operators in primitive-math#2023-04-2909:03Matthew Davidson (kingmob)+, -, rem, >=, etc#2023-04-2909:05Matthew Davidson (kingmob)I suppose I could do declare , which would be friendly even to non-kondo users, but I wanted to see how ar I could get with hooks#2023-04-2909:05borkdudeok, then, you can maybe expand in a hook to indeed, (declare +, -, ...)#2023-04-2909:05borkdudeor you could even just put declare inside of the code itself, just to satisfy kondo, it doesn't hurt anyone#2023-04-2909:06Matthew Davidson (kingmob)Right, but as I mention in the parent comment, that won't trigger an error if someone attempts to use them as a HOF#2023-04-2909:06borkdudeare they macros?#2023-04-2909:06Matthew Davidson (kingmob)(Which is probably rare, but who knows)#2023-04-2909:06Matthew Davidson (kingmob)Yes#2023-04-2909:07Matthew Davidson (kingmob)And not definlined#2023-04-2909:07borkdudeI think clj-kondo currently doesn't warn when a macro is used as a hof, but that might come sometime soon. In that case you could start doing this probably:
(declare ^:macro + ^:macro - ...)
#2023-04-2909:08Matthew Davidson (kingmob)Ahh, interesting. And in that case, no hooks are needed, I assume#2023-04-2909:08borkdudecorrect#2023-04-2909:08Matthew Davidson (kingmob)ok, lemme try that. thx!#2023-04-2909:55Matthew Davidson (kingmob)Heh, I decided to write a little declare-macro macro, and immediately gave myself the same problem all over again. laughcry#2023-04-2909:57borkdudeAnother way is to get rid of the macrology altogether and just copy paste the +, - etc macros. The low tech solution :)#2023-04-2909:58Matthew Davidson (kingmob)I'm using a Lisp, dammit. I should be able to use macros everywhere!#2023-04-2909:59Matthew Davidson (kingmob)More realistically, I'd prefer not to touch the core code of a library as old and widespread as primtive-math. It would probably be fine, but I don't really want to fool with it...#2023-04-2910:01borkdudeagreed: > the golden rule is to change nothing - unless we're adding something or fixing a bug (David Nolen, some years ago)#2023-04-2910:03Matthew Davidson (kingmob)Always a good point.#2023-04-2910:18Matthew Davidson (kingmob)Well, this is a fun one:
src/clj_commons/byte_streams/pushback_stream.clj:0:0: error: Can't parse src/clj_commons/byte_streams/pushback_stream.clj, java.lang.NullPointerException                                                                
#2023-04-2910:19Matthew Davidson (kingmob)Works in the REPL, btw#2023-04-2910:28borkdudeI think this has to do with configuration. E.g. this doesn't cause an NPE:
clj-kondo --config-dir /tmp --lint src/byte_streams/pushback_stream.clj
#2023-04-2910:29Matthew Davidson (kingmob)Interesting. Maybe some lingering reference in the imported primitive-math config.edn?#2023-04-2910:30Matthew Davidson (kingmob)No, not that.#2023-04-2910:30borkdudeIt seems to be related to the :lint-as entries#2023-04-2910:31Matthew Davidson (kingmob)...
{:lint-as {byte-streams.utils/defprotocol+  clojure.core/defprotocol
           byte-streams.utils/deftype+      clojure.core/deftype
           byte-streams.utils/defrecord+    clojure.core/defrecord
           byte-streams.utils/definterface+ clojure.core/definterface
           clj-commons.byte-streams.utils/defprotocol+  clojure.core/defprotocol
           clj-commons.byte-streams.utils/deftype+      clojure.core/deftype
           clj-commons.byte-streams.utils/defrecord+    clojure.core/defrecord
           clj-commons.byte-streams.utils/definterface+ clojure.core/definterface}}
#2023-04-2910:32borkdude
CLJ_KONDO_DEV=true clj -M:clj-kondo/dev --lint src/byte_streams/pushback_stream.clj
Execution error (NullPointerException) at clj-kondo.impl.namespace/var-classfile (namespace.clj:112).
Cannot invoke "clojure.lang.Named.getName()" because "x" is null

Full report at:
/var/folders/j9/xmjlcym958b1fr0npsp9msvh0000gn/T/clojure-10659668507427392406.edn
#2023-04-2910:33Matthew Davidson (kingmob)Seems to be related to the older byte-streams.utils/deftype+#2023-04-2910:33borkdudeseems to error here: https://github.com/clj-kondo/clj-kondo/blob/a749864535f0bb6f227310acf84f2fa7081b2684/src/clj_kondo/impl/namespace.clj#L112#2023-04-2910:34borkdudeprobably should be some->> instead of ->> or so#2023-04-2910:34borkdudeI don't even know what this code does#2023-04-2910:35Matthew Davidson (kingmob)hmmm...what's really wrinkling my brain is the code is identical in the non-depreacated ns, but that's not causing problems...somehow#2023-04-2910:35borkdudeah, it lints if the var names differ only by case#2023-04-2910:36borkdudeand somehow a var name is missing there#2023-04-2910:36Matthew Davidson (kingmob)The code between the old and new namespaces is 99% the same#2023-04-2910:36borkdudedo the protocol+ macros support the exact same syntax as the original or are there slight differences?#2023-04-2910:37Matthew Davidson (kingmob)Within byte-streams, the deftype+ macros are identical. Will have to check the usages#2023-04-2910:37Matthew Davidson (kingmob)Between projects tho, Zach frequently changed those potemkin macros, so each one has a slightly different functionality, fwiw#2023-04-2910:38borkdudeI'll try to debug some more#2023-04-2910:38Matthew Davidson (kingmob)Could it be related to the both macro?#2023-04-2910:38Matthew Davidson (kingmob)(Though that still wouldn't explain why it fails on the old ns, but not the new ns)#2023-04-2910:39borkdude
$ CLJ_KONDO_DEV=true clj -M:clj-kondo/dev --lint src/byte_streams/pushback_stream.clj
:ns byte-streams.pushback-stream :name PushbackStream
:ns byte-streams.pushback-stream :name Consumption
:ns byte-streams.pushback-stream :name ->Consumption
:ns byte-streams.pushback-stream :name trigger
:ns byte-streams.pushback-stream :name trigger
:ns byte-streams.pushback-stream :name put
:ns byte-streams.pushback-stream :name put
:ns byte-streams.pushback-stream :name expand-either
:ns byte-streams.pushback-stream :name expand-either
:ns byte-streams.pushback-stream :name walk
:ns byte-streams.pushback-stream :name walk
:ns byte-streams.pushback-stream :name prewalk
:ns byte-streams.pushback-stream :name prewalk
:ns byte-streams.pushback-stream :name both
:ns byte-streams.pushback-stream :name both
:ns byte-streams.pushback-stream :name nil
Execution error (NullPointerException) at clj-kondo.impl.namespace/var-classfile (namespace.clj:113).
Cannot invoke "clojure.lang.Named.getName()" because "x" is null
#2023-04-2910:40borkdudemaybe it's this?
deftype+ (either [PushbackByteStream] [SynchronizedPushbackByteStream])
#2023-04-2910:41borkdudethat seems to trigger the NPE#2023-04-2910:42Matthew Davidson (kingmob)Yeah, but the identical code exists in clj-commons.byte-streams, too#2023-04-2910:43borkdudeI'm getting the same NPE over there#2023-04-2910:43Matthew Davidson (kingmob)Oh? Let me check that...#2023-04-2910:44Matthew Davidson (kingmob)Huh, now I see it, too#2023-04-2910:45borkdudeI think we should make clj-kondo more robust, it doesn't handle the absence of a var name properly here, but hopefully you know what to do?#2023-04-2910:46Matthew Davidson (kingmob)No, actually#2023-04-2910:46borkdudedo you have a hook for both?#2023-04-2910:46Matthew Davidson (kingmob)Not yet. The both/either macros are convoluted, iirc#2023-04-2910:47Matthew Davidson (kingmob)And they're only internal#2023-04-2910:47borkdudewell, I think either that, or just ignore the contents of both and then declare what you need to signal the existence of vars to clj-kondo, if they are important?#2023-04-2910:48Matthew Davidson (kingmob)I've considered just separating the classes entirely for a while now. Or adding a property to indicate which is which.#2023-04-2910:48Matthew Davidson (kingmob)Sometimes the fact that Hickey forbade inheritance is super-annoying.#2023-04-2910:49Matthew Davidson (kingmob)Anyway, I know where the problm lays, anyway#2023-04-2910:49Matthew Davidson (kingmob)Thanks so much for looking into this!#2023-04-2910:49Matthew Davidson (kingmob)Have a good day!#2023-04-2910:50borkdudeyou too!#2023-05-0114:31borkdudeI don't enable new linters by default unless they are critical but I think :uninitialized-var is a good candidate to enable by default from the next release on. See e.g. https://clojurians.slack.com/archives/C06MAR553/p1682951237640419?thread_ts=1681479653.194879&amp;cid=C06MAR553 I had a similar issue in clj-kondo itself once.#2023-05-0114:33Noah BogartI think that's a good one to enable by default#2023-05-0114:34Noah Bogartrubocop will release a new linter as disabled in the initial release and then enable it in the following release after getting feedback and fixing bugs/handling edge cases#2023-05-0114:35Noah Bogart(they don't do that for all linters, just the ones that seem important)#2023-05-0114:35borkdudeyes, that's a good approach, but even then, if it's just about styling and contains something subjective/opinionated, I'm not inclined to enable it by default#2023-05-0121:44nivekuilcan kondo typecheck map literals? e.g. can it warn on (let [x {::should-be-int "foo"}] ...)#2023-05-0121:46borkdudeclj-kondo can check input maps on specific function calls, but there is currently not a way to check namespaced keys + types. this is actually not hard to implement. I think @U050CTFRT asked this in the #CPABC1H61 talk by @UKFSJSM38 at the conj, if I heard it correctly#2023-05-0121:46borkdudeI wonder if we implement it how useful it will be since e.g. clojure.spec also supports :req-un so then the user would not use the fully qualified key#2023-05-0121:53ericdalloAh yes, there is this idea of @U055NJ5CC he told me in Conj of being able to have something similar but for completion and lsp features, to be able to offer completion suggestions of known types, something to research I think#2023-05-0121:56nivekuilfor my use case, I spec keywords with malli, but using pathom we run stuff by passing maps to the logic engine instead of calling functions directly, so I don't get much mileage out of the function call linting#2023-05-0121:57ericdalloClojure-lsp has a feature of showing in a function completion suggestions of the function input map if has destructuring, but nothing checking schemas, yet#2023-05-0305:36ikitommitop-3 things that I would like to see with clj-kondo & lsp: 1. type-check arguments in function bodies 2. enable lsp auto-complete of map-fields when accessing keys from maps with known structure 3. like 2, but for EDN (“apply defaults” based on schema)#2023-05-0305:36ikitommihere’s pic of 1 & 2 from #CLDK6MFMK:#2023-05-0305:37ikitommi1: type-check function arguments in function bodies:#2023-05-0305:37ikitommi2:#2023-05-0305:38ikitommithe latter is just cursive auto-completing over all known keys in the project.#2023-05-0305:38ikitommiand 1,2,3 in comments just wishes 🙂#2023-05-0305:41ikitommiemitted clj-kondo config from above#2023-05-0307:37viestiI've been toying around the idea of writing Terraform in EDN, then spitting EDN to JSON, since Terraform accepts data in JSON format too. With Terraform, you basically describe input to various REST APIs and these inputs can be nested data. Typing out literal nested data is kind of a chore since there is at times, quite a lot of configuration data to manage, and this is why things like https://github.com/aws/aws-cdk/https://developer.hashicorp.com/terraform/cdktf/https://www.pulumi.com/ are all the rage, to get context-sensitive autocomplete, say aws.instance.inst <hit tab> => instance_type , but these things take a major effort to generate types for various programming languages, just in order to get autocompletion (well, they also get packaging of configurations as libraries too). You can get a schema of the resource types in Terraform as data, so I did a hack that registers all types as keywords, putting the resource name into the namespace of a keyword, and attribute name as name of keyword, so you can type say :aws_instance/insta <hit tab> => instance_type, if you have cider connected repl/rebel-readline into a clojure program with the keywords registered (relies on the way cider & others discovers keywords): https://github.com/viesti/clj-tf That way, you could get some basic form of intellisense, and say, discover what keys a resource contains (it get's a bit more complicated for deeply nested data though, in the hack I just put a . in the namespace to separate nesting, say :aws_instance.capacity_reservation_specification/capacity_reservation_target I guess the extreme of this could be F# kind of type providers, but for data schemas, but I might be derailing a bit 🙂#2023-05-0310:22borkdude@U055NJ5CC about 1: please post an issue. here are all the type related clj-kondo issues: https://github.com/clj-kondo/clj-kondo/labels/type%20warnings#2023-05-0311:14ikitommiwill do#2023-05-0311:23ericdalloI think 2. is harder to support, we would need to have a runtime context to check what fields are being accessed for that thread, we do have completion of all known keywords of that ns though but is generic indeed.#2023-05-0519:09ikitommidone: https://github.com/clj-kondo/clj-kondo/issues/2070#2023-05-0519:11ikitommithanks @UKFSJSM38, hopefully there would be a way get the runtime context somehow. I’m not familiar how lsp-server works here.#2023-05-0519:12ikitommithe issue was just the type-linting on clj-kondo. that would already be a BIG improvement.#2023-05-0519:14ericdallothere is one thing that I did that is related to runtime stuff and maybe could serve as idea for this problem:#2023-05-0519:14ikitommi(we know the argument clj-kondo definitions and the malli schemas here)#2023-05-0519:16ericdallowe wanted to be able to complete datomic.api and closed source code, but we didn't have the source, so no kondo analysis, so no LSP features. We created https://github.com/clj-easy/stub, a lib that generate stubs for namespaces, and clojure-lsp uses that when starting, and now we have analysis for datomic.api. stub only uses clojure to get all the vars available and spit to a dummy clojure file where LSP cals kondo and get analysis of basic stuff#2023-05-0519:17ericdalloit was kind of a hack, but something that fixed the absent of analysis for closed source, and is based on runtime#2023-05-0519:19ikitommiinteresting.#2023-05-0519:20ericdalloso, I'd avoid doing this kind of custom logic, but we extracted a lot of the complexity to that lib which helped a lot Just saying, say we manage a way to provide that data to LSP or to kondo, something like that could work maybe#2023-05-0519:31ikitommiif there is something I can do / provide extra info / something, glad to help. I think the feature set (type-linting withing function bodies, warnings on accessing keys that are not defined in argument map and a some sort of field suggester / autocompleter) would sum up to be a game-changer for clojure dx.#2023-05-0519:32ikitommiI guess this is really hard in clojure as the core functions are so generic, but clj-kondo is already doing great job here 💪#2023-05-0606:40viestiNice the stub idea, now started thinking, that could this be done for IaC stuff, to generate enough Clojure language constructs (functions with arguments typed) to be able to get autocomplete when authoring IaC configuration, just like the CDK stuff does... this generation doesn't need to happen in clojure-lsp#2023-05-0309:28dominicmIs it expected that using :lint-as def-catch-all will not set :defined-by in :var-definitions?#2023-05-0309:33borkdudenot sure#2023-05-0309:35borkdudelet's continue in thread#2023-05-0309:35borkdudeit may or may not be by design, we can change it and see what tests are breaking :)#2023-05-0309:35borkdudeor we could add another key in the analysis#2023-05-0309:36borkdudesome parts in clj-kondo rely on defined-by, so if you lint-as def than that may give you behavior that you would not get otherwise#2023-05-0309:37borkdudebut maybe this should change#2023-05-0309:37dominicmI did stumble on an issue from 2021 about including context in analysis, maybe relevant?#2023-05-0309:38dominicmBenedek was looking at reframe stuff.#2023-05-0309:38dominicmI suppose that would be very chatty though, for this use.#2023-05-0309:38borkdudethat's something else, has to do with keywords#2023-05-0309:38dominicmah, ok.#2023-05-0309:38borkdudecan you post an issue about this?#2023-05-0309:39borkdudeI'll take a look before the next release#2023-05-0309:39dominicmFor sure, thanks!#2023-05-0309:47dominicmDone!#2023-05-0309:47borkdudeThanks!#2023-05-0309:33dominicmEqually annoying, using :lint-as {ns/<> clojure.core/def} will set :defined-by to clojure.core/def rather than to ns/<>#2023-05-0309:34dominicmFwiw, I’m trying to identify uses of is inside of defspec. And this is making it difficult 🙂#2023-05-0311:33Eduardo LopesDoes it make sense clj-kondo include splint for code shape lint? https://github.com/NoahTheDuke/splint#2023-05-0311:37borkdudeI think it has good ideas so maybe some of those ideas could be ported to clj-kondo. The model is a bit different though: it just looks at the shape and not at the resolved var (so you can't distuingish from locals for example) and this could lead to false positives. The most popular of those linters we could maybe just port directly. The matching idea is pretty cool. Including another linter inside of clj-kondo will also negatively affect performance and hence editor feedback, so this would have to be carefully considered.#2023-05-0311:53Eduardo LopesI've tested it's performance on a "big" project and it took a few seconds for the entire project, linting a single file may be pretty fast. But I didn't tested enough on single files#2023-05-0311:56Eduardo LopesI didn't get why can't distinguish from locals and lead to false positives, can you explain noob friendly? Some example will help 🙂#2023-05-0311:56borkdudeThis is explained in the splint readme I believe#2023-05-0311:59Eduardo LopesThat's true I got it#2023-05-0316:15Noah Bogarthi, I built splint. I experimented with this and clj-kondo is tightly coupled to evaluation/scoping, making it hard to find a single point to drop in a call to splint/check-form or similar. I decided to build splint to not over-burden clj-kondo, and given their relative speeds, I don't think it's burdensome to run both; I see clj-kondo as helpful when actively developing, whereas I see splint as helpful after finishing a period of work (before committing or in CI).#2023-05-0316:17borkdudeyou can do a splint/check-form thing on analyze-expression** where every rewrite-clj expression is passed through, but I'm mostly concerned about the performance hit that this will incur and false positive (so I think I'd rather match on the analyzed stuff than the raw nodes)#2023-05-0316:18borkdudeperhaps there is a way to do this, but I haven't found it necessary, as things that I find really important can just be baked into clj-kondo#2023-05-0316:19Noah BogartAgreed#2023-05-0316:19borkdudein clj-kondo the matching ("is this thing inside the other thing") is usually implemented by lookup upwards in the "callstack"#2023-05-0311:53Sagar VrajalalCan I configure clj-kondo to lint files which don't have any ns declarations? Say I have a file src/main/clojure/a.clj
(defn+ ... )
and another file src/main/clojure/b.clj
(ns main.clojure.b)

(defmacro defn+ ...)
I would like to be able to hover over defn+ in a.clj and look at the docstring, arglist, etc. I am using VSCode and Calva. Is this out of scope for clj-kondo?
#2023-05-0311:57borkdudehow is clj-kondo supposed to know where defn+ comes from?#2023-05-0312:04Sagar VrajalalIt doesn't, but I was wondering if it would be possible through configuration. Something like -> For a specific file, or every file under a specific path, lint it as if its contents were defined in another namespace.#2023-05-0312:06borkdudenot possible, just write (require '[some-namespace :refer [defn+]])#2023-05-0312:09Sagar VrajalalGotcha, thanks!#2023-05-0401:38Alexander KouznetsovHow can I suppress unused-public-var for a macro that creates tests with some parameters (i. e. defmytest name [bindings])? Currently I’m using lint-as with def-catch-all or defn but that creates this unused public var warning.#2023-05-0413:12borkdude@UKFSJSM38 ^#2023-05-0413:13ericdalloif you lint-as deftest should work#2023-05-0413:13ericdalloif you cannot, you can try https://clojure-lsp.io/settings/#clojure-lspunused-public-var#2023-05-0401:39Alexander KouznetsovCan clj-kondo catch with-redefs mismatch of the number of params comparing to the original function?#2023-05-0415:58borkdudeI'm not sure what you mean by this. Could you give an example?#2023-05-0517:45Alexander KouznetsovLet’s say I have a function a that takes 4 parameters. I then make a refactor so now it takes 5 parameters. At the same time I have a test where it is redefined as (with-redefs [a (fn [_ _ _ _] mock-value)] …) , can clj-kondo warn that here it needs to be updated to take 5 params?#2023-05-0517:54borkdudecan you provide a full example? a .clj file that I can lint locally?#2023-06-1522:05Alexander KouznetsovWill something as simple as this work?
(defn x [a b] (+ a b))

(defn y [] (x 10 20))

(with-redefs [x (fn [a] a)] (y))
#2023-06-1609:43borkdudeThis currently isn't supported yet, but could be nice enhancement, please post an issue if you wish#2023-06-2800:21Alexander KouznetsovFiled https://github.com/clj-kondo/clj-kondo/issues/2126.#2023-05-0413:48Thiago Carvalho PintoI would like to suggest clj-kondo to support regex in the analyze-call, something like
{:hooks {:analyze-call {"my-project/.*/some-fn" some-dep/some-fn}}}
I have a case at work where we have a lot of namespaces that have to be included in the analyze-call list, and also a new use case that we have the project name in the namespace, so it is get harder to make this list generic without having something like a regex. What do you think?
#2023-05-0413:49borkdudeThere is a concept in the config called :ns-groups . You can make an ns group based on a regex pattern and then use that group name in the config. We could extend that to here too#2023-05-0414:32borkdudeissue welcome#2023-05-0417:28Thiago Carvalho PintoCool! This solution sounds good!#2023-05-0417:29Thiago Carvalho PintoI'll open an issue.. thank you!#2023-05-0418:03xbrlnHow can one ask clj-kondo to give a warning about an unused global declaration ? I have a function which is not used anywhere, and I would like clj-kondo to give me a warning about it. I run clj-kondo as git commit hook like clj-kondo --lint src, it uses a config file from .clj-kondo/config.edn. Ideally I want to add a keyword in that config under :linters which does that.#2023-05-0418:42borkdudeeither use: • https://github.com/borkdude/carve • clojure-lsp unused-vars both are based on clj-kondo#2023-05-0419:20xbrlnAm using leiningen, so will try carve with babashka. Thank you 🙏 #2023-05-0419:26borkdudeyou should be able to run it with lein as well: similar to this: https://github.com/clj-kondo/clj-kondo/blob/master/doc/jvm.md#leiningen#2023-05-0512:33borkdudeAnyone wants to participate in our exciting decision matrix concerning issue https://github.com/clj-kondo/clj-kondo/issues/2063? https://docs.google.com/spreadsheets/d/14bDj85LJwUrImLbt87oz9-_OMfdorU16sT4FqFdBL1s/edit?usp=sharing You can comment in this thread 🧵#2023-05-0513:00borkdude@U7RJTCH6J Does dewey use :defined-by in its analysis?#2023-05-0517:10phronmophobicThe :defined-by key is included in the weekly analysis dumps. I'm not aware of anyone is using the analysis dumps, but there's not really any way for me to know unless someone reached out in some way. Dewey itself only uses :defined-by in https://github.com/phronmophobic/dewey/blob/main/examples/stats/src/stats.clj#L52. It's part of the examples for using dewey data and I use it as part of some statistics I run when I make changes. I look at the stats of dumps from before and after the changes and make sure the results either haven't changed or provide more accurate results.#2023-05-0517:16borkdudeThanks#2023-05-0517:24phronmophobicAfter reading through the spreadsheet, the only issue I can see is if someone wanted to run some kind of analysis across time to see how codebases were changing, then the fact that :defined-by has a different meaning over time could be annoying. That situational is purely hypothetical and may never come up. Additionally, that's maybe something that should be handled on dewey's end to either rerun all analyses to provide consistent datasets across time or for dewey to provide good documentation about how the data dewey provides changes over time. Just kinda thinking out loud to provide some context.#2023-05-0517:31borkdudeoption 1 would be to not change the meaning but to introduce another key with the new meaning#2023-05-0517:31borkdudewhich is I think so far the preferred one#2023-05-1115:56stopaHey team, noob question:
(defmacro test-macro [v & body]
  `(let [~v 1] ~@body))

(test-macro v (+ 1 v))
If I write a macro that "defines" a symbol, clj-kondo will give a warning like:
Unresolved symbol: v (clj-kondo unresolved-symbol)
Is there a way I could let clj-kondo know, that for this macro, v gets defined?
#2023-05-1115:57borkdudeHey @U0C5DE6RK yes, you can do:
{:lint-as {your.ns/test-macro clj-kondo.lint-as/def-catch-all}}
or clojure.core/def or clojure.core/defn is the syntax is more like that
#2023-05-1115:58borkdudein your .clj-kondo/config.edn#2023-05-1115:58stopaSo cool! Thanks @U04V15CAJ -- just noticed I can add it as metadata too -- nice!#2023-05-1612:14Ory BandHi, I'm getting the following error + nvim completely hangs when trying to go to definiton to any function belonging to a 3rd party clojure library dependency:
; go to definition here:
(:require [com.stuartsierra.component :as component]

; i have this library in my classpath
# lein classpath
; ... /home/ory/.m2/repository/com/stuartsierra/component/1.0.0/component-1.0.0.jar ...

; and i get:

Error executing vim.schedule lua callback: /snap/nvim/2801/usr/share/nvim/runtime/lua/vim/lsp/util.lua:1157: Cursor position outside buffer
stack traceback:
        [C]: in function 'nvim_win_set_cursor'
        /snap/nvim/2801/usr/share/nvim/runtime/lua/vim/lsp/util.lua:1157: in function 'jump_to_location'
        ...nvim/lazy/telescope.nvim/lua/telescope/builtin/__lsp.lua:175: in function 'handler'
        /snap/nvim/2801/usr/share/nvim/runtime/lua/vim/lsp.lua:1394: in function ''
        vim/_editor.lua: in function <vim/_editor.lua:0>
#2023-05-1613:28borkdudeWhat does this have to do with clj-kondo?#2023-05-1613:29borkdudeIf it's an lsp-specific error, please report in #CPABC1H61#2023-05-1713:45grzm‘lo all. I generally want a way to lint just the classpaths of my code (and not the code of the dependencies). If I do something like clj-kondo --lint $(clojure -Spath -M:test:dev) , the clojure -Spath understandably returns the full classpath, including the dependencies, and clj-kondo --lint happily lints those too 🙂 . However, I really only want it to lint the :paths and :extra-paths , not the :deps and :extra-deps. I’ve got a workaround filtering the classpath for only relative paths. It works, but it feels hacky and that I’m probably missing something obvious, or there’s a piece of tribal knowledge I’m missing out on. What are others’ approaches to this? Am I thinking about it wrong (which is always a distinct possibility)?#2023-05-1713:51grzmFWIW, here’s my little bb filter:
% clojure -Spath -M:test:dev | bb -i '(->> (str/split (first *input*) #":") (remove (fn [p] (.isAbsolute (io/file p)))) (str/join ":") print)' 
test/clojure:src/clojure
#2023-05-1713:59borkdudeThere isn't any built-in solution in clj-kondo#2023-05-1713:59borkdudeIt has no knowledge of deps.edn whatsoever#2023-05-1714:00grzmMakes sense. Right now I’ve got it as a shell script. I’m thinking of porting it to a bb.edn task. Would it make sense to leverage deps.clj instead of clojure -Spath do you think?#2023-05-1714:03grzm(looks like it invokes a clojure process anyway, so I’m unlikely to see speed gains there. Not that the speed of the current method is a problem, but faster is nice :)#2023-05-1714:06borkdudeIn bb.edn you can use the (clojure …) task which invokes deps.clj but shelling out to Clojure should work too#2023-05-1714:17grzmDoes the clojure task create a separate clojure process? That was my reading of https://book.babashka.org/#tasks:clojure > The clojure function starts a Clojure process using https://github.com/borkdude/deps.clj. #2023-05-1714:21grzmHere’s what I came up with:
% cat build/src/build/elf.clj 
(ns build.elf
  (:require
   [ :as io]
   [clojure.string :as str]))

(set! *warn-on-reflection* true)

(defn relative-classpath [cp]
  (->> (str/split cp #":")
       (remove (fn [p] (.isAbsolute (io/file p))))
       (str/join ":")))
% cat bb.edn 
{:paths ["build/src"]
 :tasks
 {:requires ([build.elf :as elf])
  lint (let [relative-cp (-> (with-out-str (clojure "-Spath -A:test"))
                             (elf/relative-classpath))]
         (shell (str "clj-kondo --lint " relative-cp)))}}
% bb lint
linting took 131ms, errors: 0, warnings: 0
#2023-05-1714:22grzmnot sure if I’m happy the current factoring, but it’s Better than Bash™#2023-05-1714:22grzmThanks, @U04V15CAJ!#2023-05-1714:39grzmFor a gut check, is this seem like a reasonable thing to want to do? (programmatically determine the paths of just the project)#2023-05-1714:43borkdudewell, I've contemplated this, but then there will be people who say: I want to lint this alias, but not that alias and sometimes this and sometimes that. :)#2023-05-1714:47grzmOh, I’m not asking for this being built into anything: it a feature that’s likely to be really hard to implement and satisfy everyone. I’m just trying to figure out an idiomatic way this could be approached: munging the cp string works but feels janky. inspecting deps.edn directly also feels a bit over-involved. I’ll ask in clojure or tools-deps to see if anyone there has any ideas.#2023-05-1802:11pfeodrippeHi, is there a way to add hooks for vars with some form metadata? E.g. let's say I want to analyze a string so it cannot contain whitespaces
(def ^:my-meta aaa
  "this-is-good")     ;; Valid string

(def ^:my-meta bbb
  "this-is bad")      ;; Invalid string, clj-kondo warns
, then we could do something like
{:hooks {:analyze-meta-var {:my-meta hooks.foo/weird-meta}}}
. Ofc, this could be more general than vars if wanted (anywhere where a form metadata is found?).
#2023-05-1802:12pfeodrippeI know that I could create some bogus function as a marker wrap the string with it, but wanted to rely on metadata instead, if possible#2023-05-1807:37borkdudeThis use case hasn't come up before as far as I can remember. Perhaps you can use https://github.com/borkdude/grasp for now to write a manual check#2023-05-1812:14pfeodrippeOk, thanks!#2023-05-2014:41pfeodrippeMichiel, so a “query” written in grasp could be easily ported to clj-kondo later? Or are you saying that there is a way to use grasp with clj-kondo? #2023-05-2014:42borkdudenot currently, but just as an extra check outside of clj-kondo#2023-05-2014:43pfeodrippeGot it, thanks! #2023-05-2501:11pfeodrippeOpened an issue at https://github.com/clj-kondo/clj-kondo/issues/2088 for this (with a wip branch and a video, no PR yet, will open a PR only if you want)#2023-05-1811:03borkdude#2023-05-2117:53ThierryWith :uninitialized-var being set to default :level :warning has made my github action using delaguardo clojure-lint-action fail on 31 counts of uninitialized-var . Is there any way around this?#2023-05-2117:57Thierryfound a workaround for now#2023-05-2117:57Thierry:uninitialized-var {:level :off}#2023-05-2117:57borkdudeyes, either fix the uninitialized vars or disable the linter. I recommend fixing them though since uninitialized vars default to a truthy value while you might think they default to nil (in JVM Clojure) and this can lead to unexpected bugs#2023-05-2117:58ThierryAll uninitialized-vars in this project are :^dynamic and only used with binding. They are on purpose not initialized so they cannot be used with any pre entered value#2023-05-2117:58borkdudeI recommend initializing them to nil explicitly#2023-05-2117:59Thierrygood point, will do that and test#2023-05-2117:59Thierryneed to release tonight :melting_face:#2023-05-2117:59borkdudeno worries#2023-05-2118:07Thierrywas a quick fix thankfully, thanks!#2023-05-1814:23Thiago Carvalho PintoAbout the :type-mismatch linter, is there a way to specify an argument as a map with strict keys? (i.e. a map containing only the required and/or the optional keys, but not containing extra keys)#2023-05-1814:25borkdudecurrently not#2023-05-1918:09vemvAre there some quick reasons why I'm seeing No configs copied ? I'm expecting the Promesa exports to be copied
$ clojure -M:kondo --copy-configs --dependencies --parallel --lint "$(clojure -A:dev:test -Spath)"
No configs copied.
$ clojure -A:dev:test -Spath
src:/Users/vemv/.m2/repository/cljs-ajax/cljs-ajax/0.8.4/cljs-ajax-0.8.4.jar:/Users/vemv/.m2/repository/crate/crate/0.2.5/crate-0.2.5.jar:/Users/vemv/.m2/repository/funcool/promesa/10.0.594/promesa-10.0.594.jar [...]
#2023-05-1918:10vemvIf I uncompress that exact jar, the resource is there#2023-05-1918:11borkdudeIt could be that you don't have a .clj-kondo directory yet#2023-05-1918:11borkdudewhich is a necessary pre-condition#2023-05-1918:11borkdudeclj-kondo could of course include that in the message :-)#2023-05-1918:12vemvthat bit two of us (and CircleCi, so three :robot_face:) at work thanks for the quick help!#2023-05-2022:23Joshua GelbardI'm trying to ignore unused refers in comments. before I make a github issue—this should work, right?
;; foo.clj
(ns foo)
(comment
 (require '[a :refer [shouldnt-warn]]))
;; config.edn
{:config-in-comment {:linters {:unused-referred-var {:level :off}}}}
with the expected result being that no warnings are printed. (in fact, a warning is printed.)
#2023-05-2022:23Joshua GelbardCLI one-liner version echo "(comment (require '[a :refer [shouldnt-warn]]) a/a)" | clj-kondo --config "{:config-in-comment {:linters {:unused-referred-var {:level :off}}}}" --lint -#2023-05-2110:01borkdudeYou're right, this seems to be a bug. Github issue welcome!#2023-05-2205:45robert-stuttafordcan update this docstring now - remove "will become ..." https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#uninitialized-var#2023-05-2206:55mkvlrSeeting this with the latest clj-kondo release. Should it say what var is unresolved? src/nextjournal/clerk/viewer.cljc:299:27: warning: Unresolved var:#2023-05-2206:57mkvlroffending expression is with line 299 being the middle one
(defn inspect-fn []
  #?(:clj (->viewer-eval 'nextjournal.clerk.render/inspect-presented)
     :cljs (eval 'nextjournal.clerk.render/inspect-presented)))
#2023-05-2207:05mkvlrcan’t repro with a single file#2023-05-2207:07mkvlrah, it’s the hook we have on ->viewer-eval . Is there a way for me to tell kondo that that’s a cljs var, not a clj one in the hook?#2023-05-2207:12borkdudeI'll look into this in about an hour :)#2023-05-2209:06borkdude@U5H74UNSF Here is a potential fix but I'm not sure if this is the right one. What I'm doing here is just ignore the contents of ->viewer-eval in the clj branch and expand to syntax-quote in the cljs branch: https://github.com/nextjournal/clerk/pull/494#2023-05-2209:18mkvlrwould be awesome to get validations in clj as well, is that possible?#2023-05-2209:27borkdudeThinking.... When you write
(->viewer-eval 'nextjournal.clerk.render/inspect-presented)
in .clj , what would be "validations"?
#2023-05-2209:28borkdudeThe quoted expression in clj always points to .cljs vars right?#2023-05-2209:36mkvlryes, so looking up that var in cljs would be a validation#2023-05-2209:37borkduderight#2023-05-2210:01borkdudeI pushed a better solution now#2023-05-2410:07Carloclj-kondo displays a: Expected: map, received: seq (probably derived from malli annotations), in a function call that expects, and gets, a seq. I would like to understand why clj-kondo thinks it's a map instead. Believing it could be a stale cache problem, I deleted .lsp/.cache, but the annotation is still there. Any idea?#2023-05-2410:07borkdudeI don't have any idea without a reproduction#2023-05-2410:08Carlothank you, let me try to get a repro case 🙏#2023-05-2410:18CarloHere's a repro:
(def foo [:* :int])
(malli.core/=> bar [:=> [:cat foo] :keyword])
(defn bar [f] :ok)
(bar [1 2 3])
[1 2 3] is underlined, and the error is expected: integer. received: vector
#2023-05-2410:32CarloI updated my version of malli and the error is still there. If you can't reproduce it @borkdude I can try bumping my clojure-mode#2023-05-2410:38CarloNo, I see, it's an interaction between the malli :cat schema and :*. I though using [:vector :int] was the same but that was just because my emacs took a bit to update and clerk was messing with malli instrumentation. If I just use [:vector :int] , re-eval everything and then wait, the error is gone. thank you @borkdude!#2023-05-2410:56lassemaattaI don't use malli, but I think https://github.com/metosin/malli#sequence-schemas describes this behaviour. Check the example after the "As all these examples show, the "seqex" operators take any non-seqex child schema..."#2023-05-2417:06ericdalloI'm having some false positives with something I think it's a new linter, https://github.com/clojure-lsp/clojure-lsp/blob/f21ecb0d643acc8536cceef93ab9d5edad86a685/lib/test/clojure_lsp/feature/completion_test.clj#L220#2023-05-2417:09Noah Bogarthttps://github.com/clj-kondo/clj-kondo/issues/2086 looks to be the same#2023-05-2417:09ericdalloyes, thank you :)#2023-05-2418:34borkdudeThis false positive can be traced back to Eastwood flagging swap! as a pure function or so I think #2023-05-2418:35borkdudeI’ll still have to look into it but I’m on a trip in London right now. Any research will be appreciated meanwhile :)#2023-05-2417:57ericdalloI bumped kondo in clojure-lsp and tests started to fail, after some bisect, I found that this https://github.com/clj-kondo/clj-kondo/commit/deb8326a24d610b9756989d83d6abb8efde70fa3 made that, any thoughts @borkdude?#2023-05-2417:57ericdallohttps://github.com/clojure-lsp/clojure-lsp/actions/runs/5049440983/jobs/9058899676 in clojure-lsp#2023-05-2417:59ericdalloI think it's related with :clj-kondo/unknown-namespace removal as you mentioned before, I thought we didn't use, but I was wrong 😅#2023-05-2419:51borkdudeI don’t think it should have been in the analysis but perhaps you could explain what you were using it for #2023-05-2513:10ericdalloit has some logic to check if the var-usage has a :clj-kondo/unknown-namespace on :to to return the element itself, for example https://github.com/clojure-lsp/clojure-lsp/blob/8a8b47955c976f3ce0977889f95cd5f3a7058608/lib/src/clojure_lsp/queries.clj#L490. So, for a code like:
(ns foo) 

bar
AFAICS, now clj-kondo doesn't return any analysis for bar where it used to return something like:
{:end-row 488,
 :name-end-col 8,
 :external? false,
 :name-end-row 488,
 :name-row 488,
 :name bar,
 :from foo,
 :col 1,
 :name-col 1,
 :context {},
 :uri "...",
 :end-col 8,
 :bucket :var-usages,
 :row 488,
 :to :clj-kondo/unknown-namespace}
#2023-05-2513:11ericdallowithout analysis we can't even know that element exists, so find-references can't return that element itself, and other features wouldn't know that exists, like hover, document highlight, semantic tokens#2023-05-2513:32borkduderight, ok, let's add it back then, it's a one line change in the analysis ns
#2023-05-2614:26ericdallohttps://github.com/clj-kondo/clj-kondo/pull/2090#2023-05-2601:10diego.videcoI am trying to analyze a macro call, but I can’t seem to get it completely right: I’ve got this:
(defn defsynth [{:keys [children]}]
  (let [[_ synth-name binding-vec & body] children
        new-node (api/list-node
                  (list*
                   (api/token-node 'def)
                   synth-name
                   [(api/list-node
                     (list*
                      (api/token-node 'let)
                      binding-vec
                      body))]))]
    {:node new-node}))
The macro looks like this:
(o/defsynth rev [in 0 out 0 mix 0.5 room 0.8 damp 0.5 amp 1]
  (o/out out (* amp (o/free-verb (o/in in) mix room damp))))
And the hook output looks like this:
{:node <list: (def rev (let [in 0 out 0 mix 0.5 room 0.8 damp 0.5 amp 1] (o/out out (* amp (o/free-verb (o/in in) mix room damp)))))>}
It works for defining the vector symbols, but in the places I use it, rev still appears to not be defined. Also it doesn’t show if there are unused symbols in the let binding or if undefined symbols are used in the body. Though what I really want is to have rev understood as being defined.
#2023-05-2609:47borkdudeAre you using the newest version of clj-kondo?#2023-05-2609:48borkdudeTry with
clj-kondo --lint <src> --debug
on the command line. My suspicion is that some list node is not constructed correctly
#2023-05-2609:48borkdudealso I find it suspicious that you're destructuring on children and not on node or is there another function which receives the node?#2023-05-2618:45diego.videcoI am using this version: “2023.04.15-SNAPSHOT” (on emacs doom, with clojure-lsp)#2023-05-2618:47diego.videcoI also find int suspicious that I am destructing on children, but that’s what I am getting from this:
(-> (api/parse-string
       "(o/defsynth rev [in 0 out 0 mix 0.5 room 0.8 damp 0.5 amp 1]
  (o/out out (* amp (o/free-verb (o/in in) mix room damp))))")
      defsynth)
Am I perhaps doing something wrong?
#2023-05-2618:50diego.videcoOh got it, I had to wrap the output of parse-string in a hash-map with the :node key#2023-05-2618:52diego.videcothanks!#2023-05-2610:00borkdude@fergalbyrne You or your colleague (don't know their name, sorry) asked about midje + clj-kondo at the Funding Circle meetup. I noticed there is an exported configuration in midje here: https://github.com/marick/Midje/tree/master/test-resources/clj-kondo.exports/marick/midje#2023-05-2610:01borkdudeSee here how to "import" that configuration: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#importing#2023-10-1116:59fergalbyrneHey @U04V15CAJ sorry only seeing this now. Yes, that was almost certainly me.. Wow, that is enormously useful, and also shows how to extend/adapt it. It’ll have to be for my next job (we just both finished up with YouView, they’re more or less abandoning Clojure and the type of straightforward people who tend to use it).#2023-05-2617:16borkdudehttps://github.com/clj-kondo/clj-kondo: static analyzer and linter for Clojure code that sparks joy Just a few bugfixes since the last release! 2023.05.26 • https://github.com/clj-kondo/clj-kondo/issues/2083: fix regression with :missing-test-assertion introduced in 2023.05.18 • https://github.com/clj-kondo/clj-kondo/issues/2084: add :refers to :refer-all finding • https://github.com/clj-kondo/clj-kondo/issues/2086: false positive missing test assertion with swap!https://github.com/clj-kondo/clj-kondo/issues/2087: honor :config-in-comment for :unused-referred-var #2023-05-3012:21opqdonutI'm facing a mysterious problem where clj-kondo flags two "error: get-in with single key" in our CI job. However • We haven't enabled the single-key-in linter and it's off by default, right? • There are get-ins with single key all over the file but it only flags two • Running the same clj-kondo script locally passes cleanly Any ideas?#2023-05-3012:22borkdudeIt doesn't ring a bell. Maybe you can create a repro?#2023-05-3012:23opqdonutI'll try, but I'm not hopeful since it passes locally. But I'll keep digging.#2023-05-3012:24opqdonutCI is using 2023.07.12 and I'm on 2022.09.08, so that's one difference. Let's try upgrading#2023-05-3012:25opqdonuterrr 2023.02.17 I mean#2023-05-3012:30opqdonutoh ok, mystery solved: a colleague had enabled the linter in master and fixed all existing occurrences#2023-05-3012:31opqdonutand since the CI runs on the merge commit (`/pull/1234/merge`), clj-kondo only saw my new additions#2023-05-3012:31borkdudeok :)#2023-05-3012:32opqdonutpebcak, sorry for bothering you#2023-05-3012:38borkdudeno worries#2023-05-3012:30opqdonutoh ok, mystery solved: a colleague had enabled the linter in master and fixed all existing occurrences#2023-05-3112:05emilaasaI'd like to experiment with adding a custom linter that warns on some architectural constraints - in my concrete case I don't want us to use Java's Pattern class and the associated clj functions. Is this something that clj-kondo is intended to do, or is there another tool you recommend?#2023-05-3112:06borkdudeWe have :discouraged-var which can warn you about the usage of a var (function) in conjunction with a message that you'd like to show#2023-05-3112:06emilaasaCool, I'll try that out#2023-06-0123:12lreadSmall observations on :arglists overridden by metadata in analysis data 🧵#2023-06-0123:34lreadUsing clj-kondo v2023.05.26, given a little bb script alana.clj
(ns alana
  (:require [babashka.process :as p]
            [clojure.edn :as edn]
            [clojure.pprint :as pprint]))

(let [code (first *command-line-args*)
      config {:config-paths ^:replace []
              :analysis {:var-definitions {:meta true}
                         :arglists true}
              :output {:format :edn}}]
  (-> (p/shell {:in code
                :continue true
                :out :string}
               "clj-kondo"
               "--config" (binding [*print-meta* true] (pr-str config))
               "--lint" "-")
      :out
      edn/read-string
      :analysis :var-definitions
      pprint/pprint))
If I analyze a simple defn, I get back the :arglist-strs I would expect:
❯ bb alana.clj '(defn foo [x])'                     
var analysis for code: (defn foo [x])
[{:fixed-arities #{1},
  :end-row 1,
  :meta nil,
  :name-end-col 10,
  :name-end-row 1,
  :name-row 1,
  :ns user,
  :name foo,
  :defined-by clojure.core/defn,
  :filename "<stdin>",
  :col 1,
  :name-col 7,
  :defined-by->lint-as clojure.core/defn,
  :end-col 15,
  :arglist-strs ["[x]"],
  :row 1}]
(The encoding of arglists to strings seems like a good design choice to me, btw; no worries about edn encoding/decoding.) But if I try to analyze some code where I override :arglists with metadata like so:
❯ bb alana.clj $'(defn foo {:arglists \'([y])} [x])'
var analysis for code: (defn foo {:arglists '([y])} [x])
[{:fixed-arities #{1},
  :end-row 1,
  :meta {:arglists '([y])},
  :name-end-col 10,
  :name-end-row 1,
  :name-row 1,
  :ns user,
  :name foo,
  :defined-by clojure.core/defn,
  :filename "<stdin>",
  :col 1,
  :name-col 7,
  :defined-by->lint-as clojure.core/defn,
  :end-col 34,
  :arglist-strs ["[x]"],
  :row 1}]
My observations are that: 1. I do see the overridden :arglists under :meta 2. The :arglists under meta does not have the same string encoding as :arglist-strs (nor do we have an :arglist-strs under meta) 3. The overridden :arglists are not applied to :arglist-strs This is not a complaint. Just a thing I noticed while exploring static API analysis for cljdoc. If this is expected and intended behaviour, then I shall carry on with that understanding. If it is unintended behaviour, lemme know, I can raise at least raise an issue.
#2023-06-0212:48lreadI see, a lotta words without a question.... Apologies @U04V15CAJ, so the question is, I suppose, should arglists overridden by metadata be applied to :arglist-strs?#2023-06-0212:58borkdudeI think arglists-strs is how the arglist is written and metadata contains additional arglist if supplied as meta?#2023-06-0212:59borkdudewith :meta [:arglists] you'll get that, I think#2023-06-0213:03borkdude
$ clj-kondo --lint /tmp/arg.clj --config "{:analysis {:var-definitions {:meta [:arglists]}} :output {:format :edn}}" | jet -t ':analysis :var-definitions'
[{:col 1,
  :defined-by clojure.core/defn,
  :defined-by->lint-as clojure.core/defn,
  :end-col 5,
  :end-row 4,
  :filename "/tmp/arg.clj",
  :fixed-arities #{1},
  :meta {:arglists (quote [y])},
  :name foo,
  :name-col 7,
  :name-end-col 10,
  :name-end-row 1,
  :name-row 1,
  :ns user,
  :row 1}]
#2023-06-0213:22borkdude@UE21H2HHD I'm doing this in quickdoc: https://github.com/borkdude/quickdoc/blob/db61b35b613d3c1a7e84ea96efab6827cca20406/src/quickdoc/impl.clj#L109-L114#2023-06-0213:29lreadThanks @U04V15CAJ, so the behaviour is as intended. That works for me. Just wondered if I had found something that was unintended.#2023-06-0213:29borkdudeyeah, intended, so you can access both values if necessary#2023-06-0213:43lreadThanks, that makes sense. Do you remember why you decided to go with :arglist-strs instead of :arglists ? I'm guessing that the string encoding helped to avoid forms that might not be edn-readable?#2023-06-0213:53borkdudeyeah don't exactly remember, I think this was something that clojure-lsp needed#2023-06-0213:55lreadLike for odd stuff: (defn foo [{:keys [:bar :baz] :or {bar #"regex"}}]) :arglist-strs preserves all just fine: ["[{:keys [:bar :baz] :or {bar #\"regex\"}}]"] But if we have same as meta: (defn foo {:arglists '([{:keys [:bar :baz] :or {bar #"regex"}}])} [x]) :meta :arglists is a bit off: ([{:or {bar (re-pattern "regex")}, :keys [:bar :baz]}]) I suppose this is pretty edge-casey.#2023-06-0213:56borkduderight, I think arglists-strs is for showing and maybe it makes sense to override it from meta#2023-06-0213:56borkdudewe could change that I think#2023-06-0213:56borkdudeWhat do you think @UKFSJSM38?#2023-06-0214:00lread:arglists treatment different from :doc . For :doc we always see :doc overridden by metadata in root var map. But for :doc , unlike :arglists , an original value is never interesting.#2023-06-0214:00ericdalloYes, it's only for showing in clojure-lsp if one hover or ask the docs of a function that has the arglists meta, so it would work as well for lsp#2023-06-0214:01borkdudeok, let's do it then#2023-06-0214:01borkdudethis would also simplify quickdoc#2023-06-0214:01ericdalloJust let me know when you do as it will require minor changes in LSP#2023-06-0214:02lreadSo is original (un-overridden value) of :arglists ever interesting tho? (It isn't for my use case).#2023-06-0214:03ericdallofor LSP it is, as it checks for the meta arglists, if not present, use the root arglists-strs#2023-06-0214:03borkdudeit is only for clj-kondo to deduce the arities, but I don't think clj-kondo makes use of that API#2023-06-0214:03ericdalloOh is there other arglists besides the arglists-strs in the root?#2023-06-0214:04borkdude@UKFSJSM38 I think what you are using arglist-strs for is just for showing info, you're never interested in the "original", e.g. if a user writes:
(defn foo {:arglists '([x y z])} [& xs])
you are only ever interested in [x y z] , not in [& xs]
#2023-06-0214:05ericdalloI think so, let me double check#2023-06-0214:06lread@U04V15CAJ, I assume arities are deduced from ([x y z]) and not [& xs] , amiright?#2023-06-0214:07ericdalloConfirmed @U04V15CAJ, you are correct#2023-06-0214:07borkdude@UE21H2HHD no, :arglists metadata can't be trusted for arities#2023-06-0214:08ericdalloIt:s not only hover info, but completion, call hierarchy, signature help and other features, but all to present info only#2023-06-0214:08borkdudeit often uses informal notation like '([xs* xs?)] which is garbage for deducing arity info#2023-06-0214:08lreadyeah, that makes sense, tx#2023-06-0214:09lreadarglists overrides are only to describe usage for docs then, is that right?#2023-06-0214:12lreadSo I can write up an issue @U04V15CAJ, but in a nutshell :arglist-strs should be overriden by any :arglists metadata. Zat the idea?#2023-06-0214:13borkdudeyep!#2023-06-0214:13borkdudethanks for bringing this up, I might have just worked around the issue in the past#2023-06-0214:13lreadVery nice discussion, always a pleasure to work with @U04V15CAJ and @UKFSJSM38!#2023-06-0214:15serioga> no, :arglists metadata can't be trusted for arities @U04V15CAJ can :arities metadata be trusted for arities of def's?
(def ^{:arities #{1 2}} f ...)
#2023-06-0214:18borkdudeI've never seen that#2023-06-0214:20seriogayes, there is only :inline-arities metadata in use but I wish to be able to say kondo about arities for functions defined via def so we could utilize :arities similar to :inline-arities#2023-06-0214:21borkdudewhy not write a defn with the right arities then?#2023-06-0214:22lreadSome occurrences in the wild: https://grep.app/search?q=def%20%5E%7B%3Aarglist#2023-06-0214:23seriogawhy to write defn in case of
(def f another-ns/f)
#2023-06-0214:23borkdude@UE21H2HHD These are :arglists, not :arities - you weren't reacting to arities I guess?#2023-06-0214:24lreadooopsie, misread. ignore.#2023-06-0214:25seriogaalso there is defmulti which I can document only via :arglists#2023-06-0214:31seriogaso :arglists metadata works fine for documenting defs and defmultia (and other macros which generates global functions) but unfortunately kondo don't check arities in these case what is sad 🙂#2023-06-0214:39borkdude@U0HJNJWJH it would cause false positives which is even sadder#2023-06-0214:41borkdudeI guess clj-kondo could do a best effort attempt: if arglists only has regular symbols and not * or ? in the name, try to deduce arity info from it. But why the hassle, just define a wrapper function with a proper docstring + arglist using defn : this is what I do in my own libs, tools.build also does it, etc#2023-06-0214:56serioga> it would cause false positives which is even sadder that's why I offer some specific way to say correct data to kondo like :arities#2023-06-0214:57borkdudethat works for code you own, but not for code you don't own, like clojure.core, etc#2023-06-0214:58serioga> define a wrapper function this sounds suboptimal for me, to generate new java class and add level of indirection just for documentation purpose 🙂 I'll better live without arity check from kondo side#2023-06-0214:59borkdudeif you avoid writing a function because you'll save a Java class, you're optimizing for the wrong thing in a functional language like Clojure if you ask me ;)#2023-06-0215:21seriogafor defmulti the wrapper can be not intended...#2023-06-0215:22borkdudetrue#2023-06-0215:23serioga(phew, agreed in something) 🙂#2023-06-0215:24borkdudeI've been pondering a different solution for the above problem. If you write:
(def foo impl/foo)
clj-kondo could just inherit the arity information from impl/foo
#2023-06-0215:26seriogalet's narrow to defmulti case do you see a way to define multi-fn and teach kondo about it's arity?#2023-06-0215:27seriogawell, maybe kondo can inherit the arity information from dispatch function as well?#2023-06-0215:28borkdudeit is this issue: https://github.com/clj-kondo/clj-kondo/issues/412 feel free to comment + upvote#2023-06-0215:29borkdudeI mean, not about defmulti, just the (def foo iml/foo), you posted other stuff while I was searching this issue#2023-06-0215:29seriogaupvoted as 3rd one 🙂#2023-06-0215:35seriogaother of defmulti there are other ways to define functions using various macros so I don't mind to have clj-kondo specific way to provide arity information for linting any global vars (dynamic, declared in advance...), like #_:clj-kondo/arity ... etc.#2023-06-0215:37seriogaI tend to have universal way, not just smart inheritance or similar But inheritance is good as well 🙂#2023-06-0215:38borkdudewhat is smart inheritance?#2023-06-0215:38seriogasmart inheritance is in https://github.com/clj-kondo/clj-kondo/issues/412#2023-06-0215:40borkdudeI've also thought about a reader conditional for clj-kondo so you can specify what code clj-kondo should analyze instead of other code, or so. I'll keep thinking about it, thanks for your input#2023-06-0216:08lread@U04V15CAJ, @UKFSJSM38 issue raised: https://github.com/clj-kondo/clj-kondo/issues/2096, I look forward to your review and feedback.#2023-06-0216:10borkdudeah yes, I forgot that the :arglists is something that is evaluated and there often quoted. so presenting it as is maybe doesn't make sense :-S#2023-06-0216:45lreadYeah, we'd need to un-quote for :arglist-strs https://github.com/borkdude/quickdoc/blob/db61b35b613d3c1a7e84ea96efab6827cca20406/src/quickdoc/impl.clj#L109-L114#2023-06-0217:29borkdudeI think this might be the reason that things are the way they are since it's not guaranteed that the expression is parse-able or representable as something useful#2023-06-0217:29borkdudesince it has to be evaluated first#2023-06-0609:11joakimenHow is clj-kondo supposed to work with the pre-defined babashka-aliases? (https://book.babashka.org/#built-in-namespaces) I've gotten used to explicitly requiring everything, including the already-aliased things like json, str and pprint, partly because I like having requirements be obvious, but mostly because I don't like seeing the squiggly-line telling me that I'm referencing an unresolved namespace. Is the current design of clj-kondo meant to react on the built-in babashka aliases, or do I have some weirdness in my setup?#2023-06-0609:36borkdudeDon't rely on the pre-defined aliases outside of one-liners on the command line. When you are making a script, just use require etc with your own aliases#2023-06-0711:35imre^ this should be in the readme somewhere with capital letters 🙂#2023-06-0711:36imrewould it make sense to have a setting that requires aliases to be explicitly specified?#2023-06-0711:37borkdudeit is in the book#2023-06-0711:37borkdudethe aliases only pertain to the user namespace#2023-06-0711:38borkdudefeel free to make a PR if you think the docs can be improved at the place where you think it makes sense#2023-06-0713:37imreOh I must have missed that then. Will double-check#2023-06-0718:30André CamargoHello folks! What's the best way to keep a unit test suite of clj-kondo hooks? I'm writing a few hooks and I'd like to unit test them. Are you following some approach to achieve that?#2023-06-0718:32Noah Bogarti use clj-kondo in my CI and rely on failure to inform when my hooks might be incorrect lol#2023-06-0719:26borkdude@U04CAPVN1HS You could use clj-kondo as a JVM library and just test for :findings that it should report when you run! over some example code?#2023-06-0719:29André CamargoNice @UEENNMX0T! So you call clj-kondo in a shell script iterating over several test scenario input files and expected all them to exit code 0?#2023-06-0719:30André Camargo@U04V15CAJ hmmm to use clj-kondo as a JVM library... very interesting!#2023-06-0719:31borkdudeYes, in the JVM you can also call the hooks-api in the REPL :)#2023-06-0719:34Noah BogartI don't do anything extra, I just write what looks like a valid hook and then try it out a bunch and then rely on normal clj-kondo --parallel --lint dev src test to tell me when i've made a mistake (either in code or in the hook).#2023-06-0719:39André Camargooh, got it 😉#2023-06-0719:40André Camargothanks @UEENNMX0T and @U04V15CAJ! insightful tips!#2023-06-0814:26hairfireI just spent a couple of hours tracking down a bug that I think clj-kondo could have helped me avoid by providing a warning. The essential characteristic of the bug is shown in the code snip below:
{:my-fn #(fn [x] (* 2 x))}
The bug was introduced when I decided to change from using "#()" anonymous function syntax to "(fn [x] ...)" syntax. It would have saved me a lot of time if clj-kondo could provide a warning for this scenario. Does it make sense to catch this scenario in clj-kondo?
#2023-06-0814:29borkdudeI think so, but technically it's not wrong, but very uncommon. As an optional linter I'd say it's ok#2023-06-0814:29borkdudeissue welcome#2023-06-0814:30hairfireI will add an issue#2023-06-0915:56Noah Bogart
$ echo "(let [a 1] (let [b 2] (+ a b)))" | clj-kondo --lang cljc --lint -
<stdin>:1:13: warning: Redundant let expression. [:redundant-let]
linting took 14ms, errors: 0, warnings: 1
should this report twice? when does clj-kondo report a given error in a cljc file twice?
#2023-06-0916:02borkdudeIt deduplicates warnings#2023-06-0917:32André CamargoHello! Just to make sure I got it right how to write hooks: https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#custom-lint-warnings hooks don't need to return a map with :node, right?#2023-06-0917:33André Camargo@UKFSJSM38#2023-06-0917:35ericdallowow, I didn't know about that, looks promising#2023-06-0921:55borkdudeyeah, you don't have to return anything for custom lint warnings#2023-06-0921:53macUsing typed.clojure is giving me a lot of kondo error noice using doom emacs +lsp. I have tried with a config.edn containing: :config-in-call {typed.clojure/ann {:linters {:ignore true}} typed.clojure/defalias {:linters {:ignore true}} typed.clojure/I {:linters {:ignore true}} but I still get warnings/errors. Any ideas?#2023-06-0921:57borkdudeI think you need to get rid of the :linters key#2023-06-0921:57borkdude
{:config-in-call {my-ns/ignore {:ignore true}}}
#2023-06-0922:03macAh, let me try#2023-06-0922:12macYou are of course right abut the :linters key, but I still get warnings and errors in calls to the fucntions/macros. I have deleted both the .lsp folder and the kondon .cache folder. Should it not be ignoring all symbols in and vars inside calls to those functions/macros?#2023-06-0922:15borkdudeI think so yes, but I'm about to go to sleep. Meanwhile it would be helpful if you could provide a small repro in the form of a github repo that I could clone and try locally perhaps#2023-06-0922:16borkdudeTomorrow I'm busy with #C04VAK5U86L - will look into it after that#2023-06-0922:17macMuch appreciated. I will give that a shot.#2023-06-0923:29macSo one discovery is that the config.edn works as intended with VS Code but not with emacs.#2023-06-1000:01borkdudeif it doesn't work with emacs, perhaps you're running an older version of kondo?#2023-06-1000:18macI don't think so. I get this: ❯ clojure-lsp --version clojure-lsp 2023.06.04-19.00.17-nightly clj-kondo 2023.06.02-SNAPSHOT but perhaps emacs is using something different?#2023-06-1005:56borkdudecan you try to repro from the command line?#2023-06-1005:56borkdudeperhaps you have multiple .clj-kondo dirs inside of subdirs of the project?#2023-06-1006:14macI am getting progress now. I think I had done something silly with lint-as on top of ignoring. There is just one .clj-kondo dir 🙂#2023-06-1006:31macIs there a good solution to dealing with unresolve vars due to macro generated functions?#2023-06-1209:14borkdudeYes, this is already what config-in-call + ignore is for right#2023-06-1209:15borkdudeThere are several ways to do it. https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#unrecognized-macros#2023-06-1209:18macThanks, I did not realise that would also take care of functions generated by the macro.#2023-06-1209:24borkdudeoh macro generated functions...#2023-06-1209:25borkdudeyeah in that case a hook is probably the best. the :macroexpand hook supports copy-pasting your macro (and usually, simplifying it, just for clj-kondo purposes). Or of the syntax looks like something else, you can use :lint-as , like {:lint-as {your.ns/def-somethings clojure.core/declare}}#2023-06-1209:25macCool, thanks.#2023-06-1318:16aisamuHi! blob-wave clj-kondo correctly warns me about some incorrect calls based on type-hints alone:
(defn foo [^String x] x) (foo 1) ;; Expected: string or nil ...
But if I change ^String to almost anything else, (e.g. ^java.util.List), I can’t get it to complain. Is this expected?
#2023-06-1318:27aisamuHow it felt like to have such an incredible feature work only on String:#2023-06-1320:23borkdudeI think we can fix this, issue welcome#2023-06-1322:24aisamuWill write it once I'm back, thank you!#2023-06-1411:10aisamuDone! https://github.com/clj-kondo/clj-kondo/issues/2109#2023-06-1412:37aisamuWhoa, thanks for such a quick turnaround!#2023-06-1412:39aisamuJust to clarify: although already a very useful addition, I didn’t mean List in particular - I ran into this while hinting an arbitrary Java class#2023-06-1412:40borkdudeyou have to list every specific thing, there is no way to make it work for "everything" without mentioning things specifically#2023-06-1412:40borkdudeit's just not that common to use type hints for java.util.List, etc#2023-06-1412:41borkdudemaybe it would be more useful if we could directly use clj-kondo's keyword-like type hints, like
(defn foo [^:clj-kondo/list x])
#2023-06-1412:44aisamuDefinitely. Would it be possible to flag some of the more obvious/simpler mistakes? I wouldn’t expect it to automatically infer that invoking with class A doesn’t comply with the hint of class B, but invoking with a primitive or a known-but-different type (such as regular vector or a List) perhaps could be flagged reliably.#2023-06-1412:45borkdudeyes, that is what I proposed above right?#2023-06-1412:45aisamuThe reverse of that!#2023-06-1412:46borkdudeI meant this: https://clojurians.slack.com/archives/CHY97NXE2/p1686746495217389?thread_ts=1686680206.800839&amp;cid=CHY97NXE2#2023-06-1412:46borkdudeif you mean something else, please give an example#2023-06-1412:47aisamu
(defn foo [^software.amazon.kinesis.lifecycle.events.ProcessRecordsInput input] true) 
(foo 1)
#2023-06-1412:48borkdudeclj-kondo can't easily know if that class doesn't extend Number or so#2023-06-1412:49aisamuI see! I was indeed hoping for some reflection-based query since the hinted classes are on the classpath#2023-06-1412:50borkdudeclj-kondo doesn't inspect your runtime#2023-06-1412:50borkdudeit does some light-weight static analysis on the Java sources though, so technically it could work, but this is not a trivial issue to implement#2023-06-1412:50aisamuWhoa! It’s amazing how much it’s already able to hint without it!#2023-06-1412:51aisamuNoted - thank you for the clarification#2023-06-1412:53borkdudeIt seems that both clj-kondo type hints + Java class type hints do not conflict though, so maybe it's a nice intermediate step:
user=> (def ^:clj-kondo/long ^String x)
#'user/x
nil
user=> (meta #'x)
{:tag java.lang.String, :clj-kondo/long true, :line 1, :column 1, :file "NO_SOURCE_PATH", :name x, :ns #object[clojure.lang.Namespace 0x5f84abe8 "user"]}
#2023-06-1408:48Mateusz MazurczakWhen I do: clj-kondo --lint . it finds 0 warnings But when I do it on specific directory like: clj-kondo --lint bb/ It finds the warning. Same when I do it on specific file that the warning should be in: clj-kondo --lint bb/src/core.clj It finds warning. Any idea why?#2023-06-1408:50borkdudeno idea#2023-06-1408:52Mateusz Mazurczak😞 Any idea how to debug it? When I do clj-kondo --debug it prints the namespace, so it is scanned. And I'm on the newest clj-kondo version#2023-06-1408:52Mateusz Mazurczakclj-kondo v2023.05.26#2023-06-1408:52borkdudecan you make a small repro as a github repo, then I could try it locally#2023-06-1409:05Mateusz MazurczakOkay we've found the error. The problem is we had: bb/src/core.clj docker_images/gha/src/core.clj And that was causing the issue that there were two files with the same namespace.#2023-06-1409:07Mateusz MazurczakThere was no warning that the same namespace was defined twice from clj-kondo#2023-06-1412:54borkdudeNot sure if it's a good idea yet, but how would people feel if clj-kondo supported this:
(defn foo [^:clj-kondo/long x] (inc x))
(foo "foo") ;; type error
It seems those hints can live aside normal type hints like ^String ^:clj-kondo/string x
#2023-06-1412:56imreInteresting. What is the problem this is supposed to solve?#2023-06-1412:58borkdudegetting more type errors through static analysis. but having these annotations littered over your code might not be so nice#2023-06-1412:59imreAnd what's the benefit of these over normal type hints?#2023-06-1413:01borkdudewell, ^String technically means nullable string, since the string may be null#2023-06-1413:01borkdudeand writing :clj-kondo/list might be a bit nicer than ^java.util.List x#2023-06-1413:02jeroenvandijkAre type hints like that or presence of destructuring already used as input to clj-kondo?#2023-06-1413:02borkdudeyes#2023-06-1413:02jeroenvandijkoooh, good to know#2023-06-1413:03borkdude#2023-06-1413:03borkdudesince september 2019 or so ;)#2023-06-1413:04borkdude"presence of destructuring" not sure what you meant with this. presence of destructuring doesn't mean that the input it always a map, since technically it's safe to call get on anything#2023-06-1413:06jeroenvandijkThat’s true, but I personally never use destructuring when I would want to put something else there. So I think I would appreciate the possibility of using this information on my projects when I make a mistake. For instance I would consider it a bug if I feed a string to something where I am using destructuring#2023-06-1413:06imreSo this could serve as additional metadata to narrow the requirements for an argument?#2023-06-1413:07imreSounds similar to what one would use spec or malli for, for example#2023-06-1413:07borkdudeYes. You can already use malli to accomplish the same. https://github.com/metosin/malli#clj-kondo But not everybody wants to bring in malli or something else to their libraries#2023-06-1413:08borkdudePerhaps a more general library agnostic scheme could also be useful, that malli and clj-kondo and .. could agree upon.#2023-06-1413:12imreIs it decided how clj-kondo would handle cases where there are multiple specifications are present from #{type-hint malli clj-kondo ...}?#2023-06-1413:12imreIt does sound like this would have its uses#2023-06-1413:18borkdude@U08BJGV6E malli + clj-kondo just works because malli emits the clj-kondo configuration on disk which clj-kondo then uses. clj-kondo doesn't know anything about malli#2023-06-1413:20imreOh I see#2023-06-1414:14Noah Bogarti'm struggling to find in the docs, my apologies if it's obvious: how do i tell clj-kondo that a given cljc file will only be used in clj and bb, and NOT cljs?#2023-06-1414:14borkdude
{:cljc {:features #{:clj :bb}}}
#2023-06-1414:14Noah Bogartah thank you#2023-06-1414:15borkdudeit will actually only use known features, so it will also skip bb unfortunately, this is still work in progress#2023-06-1414:15Noah Bogartno worries#2023-06-1414:17Noah Bogartis that what this error message is about?
src/noahtheduke/splint/utils.cljc:0:0: error: Can't parse src/noahtheduke/splint/utils.cljc, No matching clause: :bb [:syntax]
#2023-06-1414:17borkdudeprobably#2023-06-1414:18borkdudethis is on the top of my things to improve#2023-06-1414:18borkdudesince it will also be useful for clojuredart, etc#2023-06-1414:18Noah Bogartyeah, for sure. no rush from me, this is an easy fix#2023-06-1414:51lreadyeah, this might be useful for cljdoc static analysis (wip) too, for, like you say clojuredart, clr, etc.#2023-06-1510:38kolstaeI've been getting clj-kondo warnings on manifold functions since 0.4.0, when using version 0.3.0 the problem disapears. Has anyone else come across this problem?
src/trank/execute.clj:43:4: warning: Unresolved var: d/error-deferred
src/trank/execute.clj:64:6: warning: Unresolved var: d/future
src/trank/execute.clj:107:30: warning: Unresolved var: d/catch
src/trank/execute.clj:140:10: warning: Unresolved var: d/success-deferred
#2023-06-1510:39borkdudecc @U10EC98F5#2023-06-1510:39borkdudecould be related to the bundled config?#2023-06-1510:40Matthew Davidson (kingmob)Hmmm#2023-06-1510:45Matthew Davidson (kingmob)@U04V15CAJ IIUC, library users have to import the distributed config, right? And only the ones exposed via /resources/ are importable by users. (Stuff I define under /.clj-kondo is only for me by default, right?) If so, I'm not sure how the bundled config is the issue, since the current one is https://github.com/clj-commons/manifold/blob/master/resources/clj-kondo.exports/manifold/manifold/config.edn, and doesn't involve those vars.#2023-06-1510:46borkdudeok makes sense. I don't know why d/error-deferred is unresolved since it's just defined using normal defn right#2023-06-1510:48Matthew Davidson (kingmob)I mean, don't get me wrong, Zach's old code is macro-heavy, and very kondo-unfriendly. It even temporarily switches namespaces in the middle of one file. So kondo errors don't surprise me; I see them all the time. But if that were the case, I'd expect the problem to appear in 0.3.0 as well.#2023-06-1510:48borkdude@U55V0HZMJ you can just add to your config: {:linters {:unresolved-var {:exclude [the-offending.ns]}}}#2023-06-1510:49kolstaeThank you both!#2023-06-1510:50Matthew Davidson (kingmob)The biggest change in 0.4.0 is the CompletableFuture support, but that should be purely additive. @U55V0HZMJ if you're willing to do a bisect with SHAs for intermediate commits, that would be pretty helpful#2023-06-1510:51Matthew Davidson (kingmob)@U55V0HZMJ Alternatively...what editor/IDE are you using?#2023-06-1510:52Matthew Davidson (kingmob)To be clear, if checking in the IDE, it might be good to double-check from the command-line. At least in Cursive, I sometimes see Cursive errors, and think they're kondo errors, or vice versa#2023-06-1510:52kolstaeI'm using IntelliJ with Cursive, but I use the command-line for this reporting (I have a git-commit hook)#2023-06-1510:53borkdudeto see those errors on the command line, be sure to lint the manifold dependency first, else you might not see the error#2023-06-1510:54kolstaeI do the following:
clj-kondo --lint "$(clojure -Spath)" --dependencies --parallel --copy-configs
clj-kondo --lint src test
#2023-06-1510:54Matthew Davidson (kingmob)@U55V0HZMJ Is there more code you could share?#2023-06-1510:56kolstaeLet me try to make a minimal example and see. I'm not sure what code to share really, it just a require with alias :thinking_face:#2023-06-1510:56Matthew Davidson (kingmob)Does sound unlikely, but it might not hurt to get more eyes on the ns#2023-06-1511:01Matthew Davidson (kingmob)Just checked the git history, and for error-deferred, it hasn't changed since 0.1.7-alpha1, so it's gotta be something else triggering it.#2023-06-1511:03borkdudesorry to have tagged you @U10EC98F5, should have checked myself first#2023-06-1511:03Matthew Davidson (kingmob)Nah, it's ok.#2023-06-1511:04Matthew Davidson (kingmob)Unfortunately, manifold is just not very linter-friendly.#2023-06-1511:16kolstaeAgain thanks for your time and effort! It's not constantly reproducible for some reason 😕#2023-06-1511:17Matthew Davidson (kingmob)Heh. Well, if that changes, let us know#2023-06-1600:06Alexander KouznetsovIf clj-kondo gives me incorrect unused-namespace warning, what’s the best way to debug to find the root cause? I see that this namespace is being used within my macro that uses clj-kondo/lint-as 'clojure.core/def setting so I’d expect it to be linted more or less correctly.#2023-06-1606:22borkdudeCan you give a repro?#2023-06-1611:58emilaasaMy debugging of the same issue usually ends up with me finding a shadowed var somewhere. 🙂#2023-06-1618:44Alexander KouznetsovI currently don’t know how to give a repro. It is one file in the private repository that has this issue. I can experiment trying to find what’s triggering it but I’m wondering if I can collect some debug info somehow. Shadowed var sounds like a very plausible explanation even though so far I haven’t found it.#2023-06-1618:46borkdudeIs this a .cljc file? Without any repro it’s difficult to say something about it #2023-06-1618:46Alexander KouznetsovThat’s a .clj file.#2023-06-1722:50sheluchinWonder how useful it would be to have a JSON Schema definition of clj-kondo's analysis data format.#2023-06-1918:19phronmophobicWas playing with stuffing the dewey kondo analysis into a database. Here's the schema so far: https://github.com/phronmophobic/dewey/blob/main/examples/deweydb/src/com/phronemophobic/dewey/db.clj#L15 You can also see where some attributes can have multiple types: https://github.com/phronmophobic/dewey/blob/main/examples/deweydb/src/com/phronemophobic/dewey/db.clj#L103 I've loaded all the data, but I'm not sure I have the right setup for actually running the queries I might be interested in.#2023-06-1919:11sheluchin@U7RJTCH6J I've been experimenting with a transformation pipeline (using https://docs.getdbt.com/) to take the dewey data and put it in a normalized SQL schema. My goal is probably a little different, since I'm mostly just trying to massage the data enough to fit into the schema my app already uses; in your case, you probably want a schema that fits all the data neatly. The reason I asked about JSON Schema is that it's such a widely used thing and helps bridge different languages. There are many tools for generating or validating data from a JSON Schema. Just seems like something that has a fit with clj-kondo's data.#2023-06-1823:28ericdalloThe LSP completion of vars of a big Nubank library that uses potemkin for the API stopped working recently and it's really affecting development since you can't the available vars of the API, is it possible to support this way of using potemkin? 🧵#2023-06-1823:28ericdalloThe issue is that this ns api is huge, so we faced a limit of vars that a namespace can have 😅 as a workaround, we found (load! "some-path") that fixed the issue, but that broke the kondo/lsp support, I'll try to explain how this behaves ATM: some_component.clj
(ns some-component)

(defn foo [] ..)
api.clj
(ns api 
  #_{:clj-kondo/ignore [:unused-namespace]}
  (:require [some-component]
            [potemkin :as potemkin]))

(load "api/chunk_1")
(load "api/chunk_2")
api/chunk_1.clj
(in-ns 'api)

(potemkin/import-vars
 some-component/foo) 
#2023-06-1823:30ericdalloAFAICS, this happens because kondo doesn't follow load , since it's a runtime thing, makes sense, but kind of break this potemkin integration and maybe other cases, I was wondering if we can fix it somehow, this is a really important lib used across hundreds of Nubank projects to develop mobile screens and have a good dev support for it is important. I thought maybe kondo could try to follow the api/chunk_1 and consider the in-ns? is it a naive thought?#2023-06-1908:57borkdudeI thought clj-kondo already follows in-ns, but if not, we could fix it#2023-06-1908:57borkdudeissue / PR welcome#2023-06-1918:47ericdallohttps://github.com/clj-kondo/clj-kondo/issues/2113#2023-06-2007:46StefanIn #clojurescript I described: https://clojurians.slack.com/archives/C03S1L9DN/p1687243572824949. Basically, when doing this:
(-> (js/Promise.resolve {:a 1})
    (.then #(:a %))
    (.then prn))
clj-kondo flags a reduntant fn wrapper. However, (.then :a) is not valid. So this is a false positive in clj-kondo. Should I file a bug for this, or should people just ignore these cases?
#2023-06-2007:50borkdudebug report is fine, perhaps we can ignore it in interop cases in .cljs since keywords cannot be used as regular JS functions (unfortunately)#2023-06-2008:02Stefanhttps://github.com/clj-kondo/clj-kondo/issues/2115#2023-06-2213:53pyrHello happy linters! I am adding hooks for some macros I wrote, and I am having issues adding a hook for this particular one: https://github.com/exoscale/ablauf/blob/master/src/ablauf/job/ast.clj#LL103C3-L111C46 I added the following hook:
(ns exoscale.ablauf-hooks)

(defn try-extract
  [sym forms]
  (if (and (list? (last forms)) (= sym (first (last forms))))
    [(vec (drop-last forms)) (drop 1 (last forms))]
    [forms]))

(defmacro try!! [& forms]
  (let [[formsf finallyf] (try-extract 'finally!! forms)
        [formsf rescuef]  (try-extract 'rescue!! formsf)]
    {:ast/type  :ast/try
     :ast/nodes [{:ast/type  :ast/seq
                  :ast/nodes (vec formsf)}
                 {:ast/type  :ast/seq
                  :ast/nodes (vec rescuef)}
                 {:ast/type  :ast/seq
                  :ast/nodes (vec finallyf)}]}))
The issue I am reaching is that while both finally!! and rescue!! are understood as valid symbols in the context of the macro, any qualified symbol used loses its qualification, leading to unused namespace errors. For instance assume the following use of the macro:
(ns my-ns (:require [ablauf.job.ast :as ast] [my-action :as action])) 

(ast/try!!
   (ast/action!! ::action/something {:payload …})
   (finally!! (ast/action!! ::action/cleanup {})))
The above would yield the following warning: warning: namespace my-action is required but never used . Is there a way I am missing to ensure qualification is preserved for the keywords used?
#2023-06-2214:00borkdudeYou could try to preserve the keywords and just emit it in another key of the expansion: :ast/_misc [keywords]#2023-06-2214:01pyrThe issue I have is that I don't know ahead of time (in my example, I don't know ahead of time that ::action/something will get called)#2023-06-2214:01pyrIf I prn the forms I see :action/something instead of ::action/something#2023-06-2214:02borkdudeah this may be a bug in the macroexpand feature of clj-kondo#2023-06-2214:02borkdudeissue welcome#2023-06-2214:02pyrok will do, thanks!#2023-06-2214:04borkdudeI'm not sure how to solve this right now, since you can't represent ::foo/bar as a normal keyword and then turn it back into a ::foo/bar node#2023-06-2214:04borkdudebut the alternative is to write an analyze-hook hook which gives you full control over these keywords as rewrite-clj nodes. it's a problem in general though so I'll have to think more about it#2023-06-2214:16pyrhttps://github.com/clj-kondo/clj-kondo/issues/2120#2023-06-2214:18pyrI think I have an ok alternative#2023-06-2214:19borkdudecool, what is it?#2023-06-2214:20pyr(still trying) In this particular case I only need the macro to walk the forms to find finally!! and rescue!! I could simply declare those as ok to be unknown and avoid the macro hook entirely#2023-06-2214:21pyr(the root issue would remain)#2023-06-2214:21borkdudeyep#2023-06-2214:21borkdudeI'll figure something out#2023-06-2214:23pyr:linters {:unresolved-symbol {:exclude [(ablauf.job.ast/try!! [rescue!! finally!!])]}}#2023-06-2214:23pyrthis did the trick, seems I was trying to be too smart#2023-06-2214:24borkdudenice#2023-06-2214:54pyrAnother question, I am following this documentation https://github.com/clj-kondo/clj-kondo/blob/85c4b763e7a1c4563722f771243ae7e2359d17f4/doc/config.md#exporting-and-importing-configuration but I cannot get a dependent library to fetch my config, even if explicitly calling copy-configs. I checked that my JAR contains clj-kondo.exports/exoscale/ablauf/config.edn#2023-06-2214:57pyrWell, clojure-lsp dump did the trick and fetched the configuration though, so it's all good#2023-06-2215:13borkdudeah good to hear.#2023-06-2215:13borkdudeyou should have gotten it with:
clj-kondo --copy-config --lint $(clojure -Spath) --dependencies
#2023-06-2215:36pyrI think it was due to the fact that the dependencies are in aliases, anyway thanks, I now have fully working imports and configs, I'll make sure all my public libraries expose kondo hooks for the macros now 🙂#2023-06-2215:39borkdudecool! thanks :)#2023-10-0109:53niclasnilssonI have a small macro that I want to be linted as fn. When I put the macro definition in the ns it’s used from, my clj-kondo linter hints works, but when I move the macro to another namespace, it doesn’t seem to pick up on the linting info. Macro
(defmacro dfn
  {:clj-kondo/config '{:lint-as {playground/dfn clojure.core/fn}}}
  [argslist & body]
  `(fn ~argslist
     (println "-> " (mapv identity ~argslist))
     (let [res# ~@body]
       (println "
#2023-10-0109:54borkdude#2023-10-0109:55borkdude#2023-10-0109:56niclasnilsson#2023-10-0109:56niclasnilsson#2023-10-0110:08niclasnilsson#2023-10-0110:08niclasnilsson#2023-10-0110:14borkdude#2023-06-2220:00Alexander Kouznetsov#2023-06-2220:01Alexander Kouznetsov#2023-06-2319:27Ben LiebermanHi, I'm getting an invalid-arity warning when using rand-int inside swap!. I don't think there's anything wrong with my usage though.#2023-06-2319:55seancorfieldWhat does the code look like?#2023-06-2319:56Ben Lieberman(swap! rand rand-int 11)#2023-06-2319:57Ben LiebermanIt says rand-int expects two args?#2023-06-2319:57Ben LiebermanI ended up switching to reset! but this seems like an incorrect lint#2023-06-2320:00seancorfieldrand-int expected one argument so it cannot be used with swap!#2023-06-2320:01seancorfield(swap! my-atom f arg) runs (f @my-atom arg) essentially. So you're trying to call (rand-int @rand 11) which is not valid.#2023-06-2320:03Ben LiebermanI see. That makes sense. And yeah I screwed up that message. My bad.#2023-06-2320:03Ben LiebermanSome days reading comprehension is not my long suit#2023-06-2616:53Ben LiebermanAn observation not 100% relevant to kondo but in CLJS passing a char to clojure.string/includes? (e.g. (clojure.string/includes? "foo" \o)) does not throw an exception (it evaluates to true) but does (probably wisely) show as a :type-mismatch . Curious if there's other instances of this in clj vs cljs?#2023-06-2709:55seriogaThere is no char type in JS, 1-char strings emulate them.#2023-06-2815:50pezI am using Garden and can’t get garden.unit/<some-unit> to lint cleanly. The units are defined with garden.unit/defunit and linting that as clojure.core/def doesn’t make a difference for my usage of the units. Is it supposed to work? Am I holding it wrong?#2023-06-2816:04borkdudelinting as should work, but you should re-analyze the dependency#2023-06-2816:14pezThanks! It worked to delete the kondo cache.
#2023-06-2816:15pezI probably should PR some clj-kondo config to Garden…#2023-06-2816:18borkdudeOr the author can add an inline config to the code. He specifically asked for this feature since he doesn't like config files and it's now in clj-kondo but I haven't heard back from noprompt. It was supposed to support meander as well#2023-06-2816:19pezAh. What’s not to like about config files? 😃#2023-06-2816:29borkdudeI don't have a problem with them#2023-06-2918:13Alice ZhaoHow do I use inline macro configuration with hooks? The documentation only shows lint-as in its example (https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#inline-macro-configuration)#2023-06-2918:28borkdudeYou can't, macro config should go into their own files#2023-06-2918:37Alice ZhaoAh, that's a shame.... having to choose between correctly linted macros and duplicate configurations across projects#2023-06-2918:53borkdudeyou don't have to duplicate your configurations across projects, you just make them part of your library#2023-06-2918:54borkdudeSee https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2023-06-2918:56borkdudehere is a list of examples: https://github.com/clj-kondo/clj-kondo/discussions/1528#2023-06-3010:50dharriganI'm probably blind, but in this example , isn't the clj-kondo line identical for each case, but the output is different?#2023-06-3010:51dharriganwait#2023-06-3010:51dharriganmy error#2023-06-3010:51dharrigandamn scrollbar not appearing#2023-06-3010:51dharrigansorry 🙂#2023-06-3010:52dharriganIn my defence, when I view the page, I see this:#2023-06-3010:53borkdudecan you please use a thread if your comments are about the same topic? thanks 🙏#2023-06-3010:52dharrigan#2023-06-3012:49borkdudeThanks for the feedback but perhaps this is more a cljdoc issue than a clj-kondo one?#2023-06-3010:53dharriganI had to squint really hard to see a missing } from the second example#2023-07-0118:46dharriganIs there a configuration knob that will tell clj-kondo to not lint a file (or set of files based upon regex?), I mean totally skip linting a file (rationale - I have in a project several edn files that are megabytes in size, and it takes a long long time for clj-kondo to lint them all (and they aren't worth linting as it's generated content)#2023-07-0118:52borkdudeI could have sworn we had an issue for this but no, this currently isn't possible. A workaround is to just enumerate the paths you do want to analyze/lint: src:test:whatever#2023-07-0118:52borkdudebut we should really just support excluding files#2023-07-0118:54dharriganThat would be appreciated, as clj-kondo (embedded with clojure-lsp) is scanning all these edn files and taking minutes for the editor to become responsive.#2023-07-0118:55borkdudeperhaps lsp does support such an exclusion pattern already?#2023-07-0118:55dharriganchecking#2023-07-0118:57dharriganCan't see anything obvious that would disable invoking clj-kondo (as the edn file are on the classpath)#2023-07-0119:01borkdudeok, made this issue and will implement it as part of the next version, hopefully somewhere next week https://github.com/clj-kondo/clj-kondo/issues/2128#2023-07-0119:01dharriganw00t#2023-07-0119:01dharriganthank you#2023-07-0119:02dharriganI'm asking on clojure-lsp to see if I've missed anything about disabling the invocation of clj-kondo for a set of files#2023-07-0119:03dharrigan(for reference, the totality of the edn files is about 81 megabytes, that I don't need to lint)#2023-07-0123:46jacob.maineThe analysis reports that the :ns of the following keyword is __current-ns__. I think it should be foo. I have a fix, but wanted to check here first… is there a reason it needs to be __current-ns__?
(ns foo)
#::{:bar 2}
#2023-07-0201:42didibusMy guess is that yes, this seems like someone went out of their way to introduce this. I think it's to indicate that :: is used, so the namespace is dynamic.#2023-07-0203:34jacob.maineI have several reasons I don’t think it was intentional… First, to clarify, by “dynamic” I think you mean “auto-resolved to the current namespace”. Is that correct? • There are many other situations that auto resolve to the current namespace, and all of them provide the true :ns. In the following, the only keyword that says :ns is __current-ns__ is the marked one. All the rest resolve to definer.
(ns definer)
  ::defined
  #::{:defined 1} ;; <-- this is the only one that resolves to __current-ns__
  (defn f [{:keys [::defined]}] defined)
  (defn f [{::keys [defined]}]  defined)
• Similarly, when using an alias, the correct namespace is always resolved. In the following, the analysis reports that the :ns of every keyword is definer (n.b. not aliased). ◦ Unfortunately, not all of these have :alias, only the first and third. I assume that’s because those are the only ones that have a /. But that reflects how they’re written, not what they mean, which is usually what the analysis is supposed to give us.
(ns aliaser (:require [definer :as aliased]))
  ::aliased/defined
  #::aliased {:defined 1}
  (defn f [{:keys [::aliased/defined]}] defined)
  (defn f [{::aliased/keys [defined]}]  defined)
• There are other attributes on analysis elements that describe how the keyword is written and what it means, including :auto-resolved, :namespace-from-prefix, :keys-destructuring, and :alias. • The analysis emphasizes what an element means, and de-emphasizes how it was written. Using __current-ns__ achieves the opposite goal. ◦ :__current-ns__ is assigned in the parser, but doesn’t seem to be intended to escape into the analysis. ◦ The analyzer has enough information to know that the ns should be definer, so it’s surprising that it discards it. OTOH, there’s an argument to support your point… If :ns were changed from __current-ns__ to definer, the analysis of the following two elements would be the same. Because of their equivalence, I don’t think it’d be possible to work backwards from the analysis to re-generate what was written. I’m not sure that’s a goal of the analysis, but it’s something to keep in mind.
(ns definer)
  #::{:defined 1}
  (ns aliaser (:require [definer :as aliased]))
  #::aliased{:defined 1}
I guess what I really wish is if it were always possible to tell both how a keyword was written and what it means. There’s a lot to keep track of. • If in a namespaced map, the keyword itself needs information from the map to distinguish between: #::{:foo 1} or #::aliased{:foo 1} or #:literal{:foo 1}. • If in destructuring keys, the keyword needs information from the destructuring to distinguish between :keys [foo], ::keys [foo], ::aliased/keys [foo] and :literal/keys [foo]. ◦ In destructuring, it would also be nice to know if the user wrote :keys [foo] or :keys [:foo], which have the same meaning. • On the keyword itself, you need to distinguish between :foo, ::foo, ::aliased/foo, :literal/foo, and :_/foo. The last has special meaning if and only if in a namespaced map or in destructuring.
#2023-07-0204:20jacob.maineI have a tendency to be long-winded. 🙂 A more succinct way to say all of that is: I’d like to know the resolved namespace of (ns foo) #::{:bar 1}. Is changing the analysis to replace __current-ns__ with foo the best way to do that?#2023-07-0206:14borkdudeI don't know why it's __current-ns__ , perhaps just a bug, feel free to post an issue + proposal PR#2023-07-0315:09pezIf I have two files with the same namespace, say a/foo/bar.clj and b/foo/bar.clj with ns foo.bar, I can evaluate symbols defined in a from b, but clj-kondo will warn if the symbols are not defined in b. I guess this is by design, but wonder if there is a chance a config could be added to make clj-kondo treat b as part of a, or something?#2023-07-0315:32borkdudeif you have two files with namespaces of the same name, they will override#2023-07-0316:26pezYou mean in the repl?#2023-07-0316:39pezAlternatively. Can I disable linting for directory tree?#2023-07-0316:42pezSimilar to.
(ns main.core
  {:clj-kondo/config 
   '{:linters {:unresolved-symbol {:level :off}}}})
But for all files in some tree.
#2023-07-0316:56borkdudenot yet, there's an open issue which I will address for the next release#2023-07-0316:56borkdude> You mean in the repl? No, for clj-kondo#2023-07-0317:04pezIs that a no to my question? 😃#2023-07-0317:04borkdude?#2023-07-0317:05pez> if there is a chance a config could be added to make clj-kondo treat b as part of a, or something?#2023-07-0317:07borkdudeyes no ;)#2023-07-0317:07borkdudeI don't intend to support that#2023-07-0317:08pezPity. Then will look forward to the directory level config instead. 😃#2023-07-0317:09seancorfield@U0ETXRFEW I'm curious how that is structured... I assume you're loading files explicitly here, not just relying on the classpath?#2023-07-0317:14pezYes, loading them in the repl only. It’s Fiddle files, as discussed in this podcast episode: https://clojuredesign.club/episode/014-fiddle-with-the-repl/ Personally I can ignore that the files look like christmas trees of squiggles, but ’m adding some extra support in Calva for fiddle files, and was hoping I could figure out a convenient way to remove the error messages.#2023-07-0703:48joshchoI want https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#inline-macro-configuration for clojurescript macros, but am having difficulty setting it up. I have in utils.clj:
(ns slix.utils)
(defmacro with-simple-subs
  {:clj-kondo/ignore [:unresolved-symbol]}
  [subs & body]
  `(let [~@(apply concat (map to-simple-sub subs))]
     ~@body))
and in utils.cljs:
(ns slix.utils
  (:require-macros [slix.utils :refer [with-simple-subs]]))
(with-simple-subs [a b c])
I get linting errors in a, b, and c, when I expect those linting errors to be ignored.
#2023-07-0711:23borkdudeDo you have a recent version of clj-kondo? Did you lint the original macro? Do you see anything in .clj-kondo?#2023-07-0812:38Vikas GautamI am stuck at trying to add a custom hook to lint a macro defined in my https://github.com/Vikasg7/jdsl parser combinator library, I wrote. I tried to follow the hooks.md in the clj-kondo docs but failing. Here is the https://github.com/Vikasg7/jdsl, please checkout to clj-kondo-hook branch. As I am going with macroexpand approach in the hooks.md, here are the steps I followed. 1. I created the dev profile with a dependency on lein-clj-kondo as below. It enabled me to test my hook in the vscode using calva. :profiles {:dev {:dependencies [[com.github.clj-kondo/lein-clj-kondo "0.2.5"]]}} 2. I copy pasted jdsl.basic/do macro to hooks.basic/do in the .clj-kondo folder. I successfully tested my hook using following.
(def macro
  "(jb/do
      jp/any-char
      (jp/any-char)
      (jp/char \\a)
      (a <- (jp/char \\a))
      (b <- jp/any-char)
      (_ <- jp/any-char)
      (jc/return [a b]))")

;; following print statement works and prints the exact same api/list-node as the
;; analyze-hook would print as I tested earlier.
(println (api/macroexpand #'hooks.basic/do (api/parse-string macro) {}))
;; prints following list-node as printed by analyze-hook approach
;; <list: (clojure.core/fn [ts] (clojure.core/let [[_ ts] (#function[jdsl.basic/run] jp/any-char ts) [_ ts] (#function[jdsl.basic/run] jp/any-char ts) [_ ts] (#function[jdsl.basic/run] (jp/char \a) ts) [a ts] (#function[jdsl.basic/run] (jp/char \a) ts) [b ts] (#function[jdsl.basic/run] jp/any-char ts) [_ ts] (#function[jdsl.basic/run] jp/any-char ts)] (#function[jdsl.basic/run] (jc/return [a b]) ts)))>
3. I added the corresponding entry in the config.edn file as below: {:hooks {:macroexpand {jdsl.basic/do hooks.basic/do}}} 4. saved and restarted the vscode. 5. Checked the jdsl.basic-test in the test folder but linter is not linting the usage of do macro. 6. I tried following command as well but failed with and without --cache false npx clj-kondo --lint src test 7. here is the error output I am getting.
E:\Desktop\clojure\jdsl>cat test\jdsl\basic_test.clj | npx clj-kondo --lint -
WARNING: file jdsl/basic not found while loading hook
WARNING: error while trying to read hook for jdsl.basic/do: Could not find namespace: jdsl.basic.
<stdin>:37:16: error: Unresolved symbol: a
<stdin>:37:18: error: Unresolved symbol: <-
<stdin>:38:16: error: Unresolved symbol: b
<stdin>:40:15: error: jdsl.char-parser/skip-any-char is called with 0 args but expects 1
<stdin>:41:16: error: Unresolved symbol: e
<stdin>:49:16: error: Unresolved symbol: _
<stdin>:50:15: error: jdsl.char-parser/any-char is called with 0 args but expects 1
linting took 4859ms, errors: 7, warnings: 0
I tried to find and follow the Github issue but couldn't find the solution. PS. looking at those warning, seems like clj-kondo is unable to resolve the jdsl.basic/do macro located in src/jdsl/basic.clj file, not sure how to fix that. VERSION info - npx clj-kondo version v2023.05.26 calva version info- Calva version used: v2.0.374 clojure-lsp version used: 2023.07.01-22.35.41 clj-kondo version used: 2023.06.02-SNAPSHOT Clojure version - 1.11.0 Thanks in Advance. Vikas
#2023-07-0815:19borkdudeThere's a lot of stuff here. I think it's better to put this in a Github reo that I can run locally#2023-07-0815:20borkdudeBut surely
WARNING: file jdsl/basic not found while loading hook
WARNING: error while trying to read hook for jdsl.basic/do: Could not find namespace: jdsl.basic.
is the root of the problem
#2023-07-0815:21Vikas GautamThanks for reply Sir. Repo is ready. https://github.com/Vikasg7/jdsl checkout to clj-kondo-hook branch.#2023-07-0815:24borkdudeThe issue is with:
(:require [jdsl.basic :as jb :refer [run]])
#2023-07-0815:24borkdudeif you want to run this namespace in the clj-kondo hooks interpreter, you need to add it to the config#2023-07-0815:24Vikas Gautamoh... what is the keyvalue pair to add it?#2023-07-0815:26borkdudewhy do you want to do this?#2023-07-0815:26borkdudeWhat is the purpose of returning:
(list run form 'ts)
#2023-07-0815:27Vikas Gautamyou can read the do macro doc string.#2023-07-0815:29Vikas Gautamevery form is a parser and I want to run the parser with the token-stream ie. ts as argument and pass the ts to the next parser call.#2023-07-0815:29borkdudeI think what you are looking for is really:
(ns hooks.basic
  (:refer-clojure :exclude [do])
  (:require [jdsl.basic :as-alias jb]))

(defn- expand->bindings 
  "Expands `parser`, `(parser)`, `(a <- parser)`, `(parser args)` forms 
   in the do macro to `let` bindings."
  [form]
  (if-not (list? form)
    [['_ 'ts] (list `jb/run form 'ts)]
  (if (= 1 (count form))
    [['_ 'ts] (list `jb/run (first form) 'ts)]
  (let [[sym op prsr] form]
  (if (= '<- op)
    [[sym 'ts] (list `jb/run prsr 'ts)]
    [['_ 'ts] (list `jb/run form 'ts)])))))

(defn- expand->body
  "Expands the `parser`, `(parser)`, `(parser args)` form 
   in the do macro to `let` body"
  [form]
  (if-not (list? form)
    (list `jb/run form 'ts)
  (if (= 1 (count form))
    (list `jb/run (first form) 'ts)
    (list `jb/run form 'ts))))
#2023-07-0815:29borkdudeyou don't want to return a list with the function from your library, but a list with a symbol that points to the function of your library#2023-07-0815:31Vikas Gautamyes, it sounds correct, I think I might have tried api/token-node 'jdsl.basic/run along that spirit.#2023-07-0815:31Vikas Gautamlemme test above.#2023-07-0815:40Vikas Gautamit worked thanks, so will it work If I lein-git-down and use this as dependency in my other repo? Actually, I use this library to make parser for the interpreter, I am writing in clojure. Also, is :as-alias any different from :as here? Thanks for the quick help. Really Appreciate it.#2023-07-0815:43borkdudeas-alias only introduced an alias, but does not load a library#2023-07-0815:44borkdudeyou can read here how to "export" your configuration so it will be visible to anyone who uses your library: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2023-07-0815:44borkdudehere are lots of examples: https://github.com/clj-kondo/clj-kondo/discussions/1528#2023-07-0815:45Vikas GautamSure, thanks once again. You are a life savor. I was stuck on this for 2 days.#2023-07-0822:04hifumi123Which version of clj-kondo was the :misplaced-docstring linter introduced? It seems that lein-clj-kondo doesn't have it, but the version bundled with the latest clojure-lsp does#2023-07-0822:09borkdudeI don't know, but you can include a newer clj-kondo as an extra dependency so lein-clj-kondo uses that one#2023-07-0822:10borkdudealso you can probably just use a git blame on src/clj_kondo/impl/config.clj to check yourself#2023-07-0822:10ericdalloalso, there is the clojure-lsp diagnostics which should behave the same as the editor + extra linters you see in the editor#2023-07-0822:11hifumi123Thanks, @U04V15CAJ and @UKFSJSM38, I will try doing these things soon#2023-07-0900:28hifumi123I attempted using [clj-kondo "2023.05.26"] as a managed dependency, but lein-clj-kondo does not pick this up when I use it as a plugin. Am I supposed to use exclusions?#2023-07-0901:09hifumi123OK I think I see the problem — lein-clj-kondo is not evaluating code in the project, so it is always going to use its own clj-kondo version, regardless of what the project specifies#2023-07-0906:46borkdudeDoes lein not allow to insert newer deps into plugins? That would surprise me about a dep management tool#2023-07-0908:33hifumi123The problem is there are multiple evaluation contexts in leiningen#2023-07-0908:33hifumi123To ensure proper isolation, you can either eval in project, eval in leiningen, or even set up your own classpath entirely#2023-07-0908:34hifumi123It looks like lein-clj-kondo evaluates in a context isolated from the project, so there is nothing the project can do to mess with the plugin#2023-07-0908:34hifumi123Likewise, whatever dependencies the lein-clj-kondo plugin uses will not mess with the project’s classpath#2023-07-0908:35hifumi123so while you are able to use exclusions, managed dependencies, etc. in a project, none of these will ever end up affecting lein-clj-kondo since lein-clj-kondo does not eval-in-project to begin with#2023-07-0908:36hifumi123for now i have decided to fork lein-clj-kondo, update the dependency, and deploy it in a private maven repository#2023-07-0909:28borkdudeFeel free to PR the update#2023-07-1003:51hifumi123after some investigation, i realized that https://github.com/clj-kondo/clj-kondo/issues/2001 made the following NOT trigger misplaced docstring
(deftest foo
  "not a docstring"
  (is ...))
#2023-07-1003:51hifumi123so clojure-lsp is using an older version of clj-kondo before this was merged, presumably, because clojure-lsp does warn me about it#2023-07-1003:52hifumi123this resulted in a bit of a rabbit hole finding out why clojure lsp would complain about code that passed lint tests in CI 😄#2023-07-1003:58hifumi123
% clojure-lsp --version
clojure-lsp 2023.02.27-13.12.12
clj-kondo 2023.02.17
alright, that explains everything now
#2023-07-1004:01hifumi123I am working on a project with a friend who is very new to clojure and makes a lot of silly mistakes. So I have many clj-kondo linters set to :level :error so that he avoids many bad writing styles. In particular, he attempted writing a docstring for a test, but I dont think deftest even accepts docstrings. The :misplaced-docstring linter was helpful in finding this mistake. But later versions of clj-kondo no longer do this for deftest forms.#2023-07-1008:27borkdudeAFAIK deftest never took a docstring#2023-07-1008:57hifumi123Yeah. It looks like someone requested to make the :misplaced-docstring linter not warn about strings in a deftest form, though I personally liked the old behavior.#2023-07-1009:14borkdudeIn general this should be reported as unused-value but it doesn't do this right now. I'll fix that#2023-07-1009:14borkdudee.g.:#2023-07-1009:19borkdudehttps://github.com/clj-kondo/clj-kondo/issues/2132#2023-07-1011:02ericdalloBTW you have a outdated clojure-lsp, so outdated kondo, latest version is from July, you are using one from February#2023-07-1013:30zimablueI just came to say that being able to put the lint-as in the macro metadata is great and I just found out about it and thank you for making that change#2023-07-1119:19Brandon StubbsHey, while using the analysis api on the :var-definitions there is an option to get the arglists as a string. What would be the best way to get the definition sexp as a string, or is this out of scope?#2023-07-1120:17borkdudejust parse it as EDN, I'd say#2023-07-1120:26Brandon StubbsJust to check we are on the same page: Say I have the file foo.clj
(ns foo)

(defn foo
  []
  (inc 1))
I run analysis on this and I get:
[{:arglist-strs ["[]"]
  :col 1
  :defined-by clojure.core/defn
  :defined-by->lint-as clojure.core/defn
  :end-col 11
  :end-row 5
  :filename "/Users/brandonstubbs/projects/x/src/foo.clj"
  :fixed-arities #{0}
  :name foo
  :name-col 7
  :name-end-col 10
  :name-end-row 3
  :name-row 3
  :ns foo
  :row 3}]
In order to get "(defn foo\n []\n (inc 1))" parse it as edn for that?
#2023-07-1120:28borkdudeAh sorry, the entire definition. My recommendation is to use rewrite-clj and iterate over the nodes, until the positions match up. And then just use str on the node, this will give you the definition.#2023-07-1120:29borkdudehere is a similar function, but then the opposite: it removes definitions from the original code https://github.com/borkdude/carve/blob/cb621317ae1582869c8bd8f1a47cf57a3598d803/src/carve/impl.clj#L118#2023-07-1120:31Brandon StubbsOk great thank you I will do that, is this something you do not want in scope of this lib?#2023-07-1120:31borkdudenot in scope for clj-kondo. it throws away all whitespace so it doesn't even know the original node anymore#2023-07-1120:33Brandon StubbsI would prefer the whitespace removed, what I am looking for is a quick way to say has this definition changed since this file was analysed#2023-07-1120:34borkdudewhy not just look at the substrings based on the entire file#2023-07-1120:34borkdudeyou don't even need rewrite-clj for this#2023-07-1120:35Brandon StubbsBusy writing something that does a bit of tree shaking for building, similar to turbopack in the js world. But on second thought, I think whitespace should matter as if someone adds a newline that’s important#2023-07-1120:36borkdudeok, then you can just focus on the lines and columns that clj-kondo reports and check the contents in the file#2023-07-1120:36borkdudejust using raw string comparison#2023-07-1120:37Brandon StubbsYeah that will actually be great! Thanks for the discussion 😄#2023-07-1207:13mkvlrmorning, the following triggers a warning: Unused private var nextjournal.clerk.eval/nippy-tweaks
(defonce ^:private nippy-tweaks (do ,,,))
I’m using the defonce to run setup code that I’d like to only run once so I don’t think it should trigger a warning. Can file an issue if you agree. Or is there another recommended pattern?
#2023-07-1207:35borkdudeThis is a pretty rare case. For rare cases you can use an ignore hint.#2023-07-1207:58genmeblogI've just hit the same problem 🙂 (adding one custom, global listener to the awt event dispatcher)#2023-07-1208:03borkdudeLike I said:
#_{:clj-kondo/ignore [:unused-private-var]}
(defonce ^:private dude 42)
There are cases in which you do want the warning. If you only use defonce for side effects (which is only a subset of what you can use defonce for), just use this.
#2023-07-1208:04mkvlrso you like kondo to warn when in doubt?#2023-07-1208:05mkvlrfor me it’s the opposite#2023-07-1208:05borkdudein this case clj-kondo cannot read your mind why you are using defonce, it can be argued both ways#2023-07-1208:06mkvlrbut for these cases you’d like to err on the side of warnings?#2023-07-1208:06genmeblogNo worries! Just wanted to share that case can be more common than you think.#2023-07-1208:14borkdudeWhy are you even creating a var when all you want is some piece of code to be executed once. I think it's just evidence of an edge case of an edge case. Automatically deciding no not warn here is too opinionated. This is exactly why we have ignore hints.#2023-07-1208:15mkvlrI guess we want different things from kondo#2023-07-1208:15borkdudefine#2023-07-1208:16mkvlrif you want kondo to warn when in doubt I’ll know not to bring up things like this in the future#2023-07-1208:18borkdudeThis is not in general the case, I'm only talking about this specific case#2023-07-1208:18borkdudeI don't find the evidence to change the current behavior compelling enough, I can see cases where it would work against you#2023-07-1208:18borkdudeMight change in the future though#2023-07-1208:20mkvlrhmm, work against you = some dead code at worst?#2023-07-1208:21mkvlrhow would you write setup code that should only be executed once?#2023-07-1208:21mkvlrneed some state to store that it ran already#2023-07-1208:36borkdude> hmm, work against you = some dead code at worst? exactly, clj-kondo first and foremost is a tool to keep your code clean and minimal, hence the name :) I've used defonce myself in this way but it's not the only way people use defonce. I think not warning would go against the name of the tool ;)#2023-07-1208:37borkdudeso just use the ignore hint is the current advice. we could introduce some convention for unused vars that start with an underscore, but this is pretty rare, in the sense that, it has never come up before. I'd be open to that option though#2023-07-1208:40mkvlrmakes sense now that you spell it out like this#2023-07-1208:41mkvlrI’m less interested in clean & tidy code but want things to not explode#2023-07-1208:42borkdudeI think it's easier to make a mess than to keep things tidy, clj-kondo errs on the side of the latter#2023-07-1208:43borkdudealso I didn't have my coffee yet and I was a bit grumpy, sorry for that#2023-07-1208:45mkvlrdidn’t get that feeling here, all good! Enjoy your !#2023-07-1208:46borkdude
(defonce ^:private _foo ...)
is something we could do though.
#2023-07-1208:47mkvlryeah, guess it would go well together with the handling of fn unused args#2023-07-1208:47borkdudeok, I'll add that#2023-07-1209:16borkdudedone: https://github.com/clj-kondo/clj-kondo/commit/d539034340fa046b139ac3268b43287a34e974fb#2023-07-1209:17mkvlrexcellent, thank you!#2023-07-1216:05simonkatzAfter upgrading clojure-lsp and using the new-ish feature that allows clj-kondo metadata to be added to macros (eg {:clj-kondo/lint-as 'clojure.test/deftest}), I’m now seeing .lock files in my .clj-kondo directories. What are these .lock files? Should I commit them into version control? There are also inline-configs directories. Should I commit them into version control? (Sorry if I’ve missed documentation that covers this.)#2023-07-1216:08simonkatzOK; thank you!#2023-07-1310:04mkvlrrunning into this warning:
(deftest offset
  (let [!offset (atom 0)]
    (testing "has correct values"
      (is (= 0 @!offset))
      (swap! !offset inc) ;; TRIGGERS warning: missing test assertion
      (is (= 1 @!offset)))))
should I split this up into two testing blocks?
#2023-07-1310:45borkdudeI think I've already fixed this one on master, let me check#2023-07-1310:45borkdudewhat version are you using#2023-07-1310:47borkdudeI think it might already be fixed in the latest release btw#2023-07-1310:47borkdudehttps://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#20230526#2023-07-1319:53mkvlrthank you, can confirm it’s fixed after an upgrade#2023-07-1319:42borkdudehttps://clojurians.slack.com/archives/C06MAR553/p1689277284546469#2023-07-1414:49Brandon StubbsAm I able to get the gen-class from the analysis api?#2023-07-1414:51borkdudeCan you elaborate, not sure what you mean#2023-07-1414:52Brandon StubbsRight now analysis can return the namespace-definitions I was wondering if there was a place it would let me know which namespaces had a gen-class included#2023-07-1415:04borkdudeHmm, I don't think it's emitted anywhere right now#2023-07-1415:07Brandon StubbsI would be happy to raise an issue and create a PR if you would like?#2023-07-1415:11borkdudesure, issue with a proposal would be fine as a first step!#2023-07-2018:05Jake PearsonHi. I was wondering what my best course of action is if I using a macro that is like a def (but not quite). We use clojure-metrics which has macros that are used like (metrics/defhistogram registry metric-name). Is there a way to configure lint-as to use the 2nd arg instead of the first? Maybe something like:
:lint-as {metrics.histograms/defhistogram clojure.core/def {:named-arg 2}}
Or other suggestions would be appreciated.
#2023-07-2018:08borkdudeThis isn't possible but you are allowed to write a hook which expands into anything you want#2023-07-2018:09Jake PearsonThanks, I'll take a look at hooks.#2023-07-2018:09borkdudeSee https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand#2023-07-2018:12Jake PearsonReally helpful, I didn't see that before.#2023-07-2018:32seancorfield@U05EHGS99DZ We use that lib at work and have hooks for lots of stuff in it:
(ns hooks.metrics.histograms.defhistogram
  (:require [clj-kondo.hooks-api :as api]))

(defn defhistogram [{:keys [node]}]
  (let [[registry sym] (rest (:children node))
        rewritten
        (api/list-node
         (list
          (api/token-node 'def)
          sym
          (api/string-node "dummy")
          registry))]
    {:node rewritten}))
#2023-07-2018:33seancorfieldAnd similarly for counter, meters, and timers.#2023-07-2018:33borkdudehmm, perhaps those hooks can be contributed back to the library#2023-07-2018:34seancorfieldYeah, we've developed them one-by-one over time so it was a bit frog-in-a-pot and we never quite got the momentum to contribute them back...#2023-07-2018:34borkdudewait, is it (def sym something something)?, I thought the sym came as the second argument as @U05EHGS99DZ said#2023-07-2018:35borkdudeif that is the first, you could also use {:lint-as {... clj-kondo.lint-as/def-catch-all}}#2023-07-2018:35seancorfield(defhistogram registry sym ...)#2023-07-2018:35borkdudeah ok#2023-07-2018:35borkdudeoh right, the expansion swaps it facepalm#2023-07-2018:37seancorfieldI didn't dig into the metrics lib docs to see what else should be hooked or whether extra args might be supported so I viewed them as "just enough" to shut clj-kondo up 🙂#2023-07-2018:38borkdudefair enough :)#2023-07-2018:38seancorfieldI don't know how well (if?) the library is maintained -- it has had no updates for three years at this point...#2023-07-2018:40borkdudeI'd be happy to receive a partial config here as well: https://github.com/clj-kondo/configs Partial is better than none and usually other people drive by to complete it, if the library is used by enough people#2023-07-2018:44seancorfieldI might take a look at that at some point but I don't know when. Having kind of a bad month (dealing with a death in the family) and my OSS work has taken a back seat to make space for personal stuff right now.#2023-07-2018:45borkdudeNo rush at all. Sad to hear, I wish you and your family the best.#2023-07-2019:38Jake PearsonI probably won't get to it this week, but will try to implement the hooks soon. If I get it working, I'll submit a PR to the config repo you mentioned. Thanks.#2023-08-0721:10Jake PearsonHi, I finally have some time to work on this. I haven't gotten clj-kondo to pick up the macro I wrote. I made a file .clj-kondo/metrics/histograms.clj with:
(ns metrics.histograms)

(defmacro defhistogram
  ([_registry histogram-name] `(defhistogram ~histogram-name))
  ([histogram-name] `(def ~histogram-name "histogram")))
Then added the following to .clj-kondo/config.edn
:hooks {:macroexpand {metrics.histograms/defhistogram metrics.histograms/defhistogram}}
But then when I run clj-kondo , I still see unresolved symbol:<metric name> . I tried the $ example in the docs and it worked. Do I need to do something special when I'm creating a replacement macro for a library I'm importing versus one in my own source tree?
#2023-08-0721:15borkdudeTry some printing in the macro, to see if this is outputted to the console#2023-08-0721:50Jake Pearson
(ns metrics.histograms)

(println "!!! first")

(defmacro defhistogram
  ([_registry histogram-name] `(defhistogram ~histogram-name))
  ([histogram-name]
   (println "!!! second" histogram-name)
   `(def ~histogram-name "histogram")))
I see first, but not second when I run
clj-kondo --config .clj-kondo/config.edn --lint src/fortune/metrics.clj
from my terminal. If I add (defhistogram nil test-metric) to my file I get second in the output !!! second test-metric , but not for my other usages of the macro.
#2023-08-0815:03Jake PearsonI made a fresh repo with as small of an example as possible and it worked. Now to figure out what the difference is.#2023-08-0815:18Jake PearsonFigured it out. My macro didn't work very well. I had:
(defmacro defhistogram
  ([_registry histogram-name]
   `(defhistogram ~histogram-name))
  ([histogram-name]
   `(def ~histogram-name "histogram")))
Once I changed it to:
(defmacro defhistogram
  ([_registry histogram-name]
   `(def ~histogram-name "histogram"))
  ([histogram-name]
   `(def ~histogram-name "histogram")))
It started working. I think this was hinted at in the doc about using fully qualified names when calling functions from within a macro.
#2023-08-0815:19Jake PearsonThis works too
(defmacro defhistogram
  ([_registry histogram-name]
   `(def ~histogram-name "histogram"))
  ([histogram-name]
   `(defhistogram ~histogram-name)))
I guess order of defs was important.
#2023-08-0815:30Jake PearsonThanks for the help.#2023-07-2021:06hifumi123How does clj-kondo detect whether a required namespace has been used? In Helix, when using react/forwardRef, react is incorrectly marked as an unused namespace, which is a bit annoying because its clearly used. Here is a simple example to demonstrate this issue
(ns some.namespace
  (:require [helix.core :refer [$ defnc]]
            ["react" :as react]))

(defnc component
  {:wrap [(react/forwardRef)]}
  [_ ref]
  ($ :div {:ref ref} "hello"))
Using [clj-kondo "2023.07.13"] and [lilactown/helix "0.1.10"] . You can use the following shadow-cljs.edn for an example project
{:source-paths ["src"]
 :dependencies [[lilactown/helix "0.1.10"]]
 :builds {:app {:target :browser
                :output-dir "public/js"
                :asset-path "/js"
                :modules {:base {:entries [some.namespace]}}}
#2023-07-2021:10borkdudeI suspect that the (react/forwardRef) is not handled properly by this hook: https://github.com/lilactown/helix/blob/master/resources/clj-kondo.exports/lilactown/helix/clj_kondo/lilactown/helix.clj Perhaps the metadata is lost or something. I can take a closer look tomorrow maybe. cc @U4YGF4NGM#2023-07-2021:12hifumi123Ah yeah, this is more of a hooks issue rather than clj-kondo issue. Thanks for pointing this out#2023-07-2217:31lilactownyes I've seen this happen. clj-kondo does not consider vars passed to metadata as "used"#2023-07-2217:32lilactownor rather perhaps my hook does not treat it right#2023-08-0721:10Jake PearsonHi, I finally have some time to work on this. I haven't gotten clj-kondo to pick up the macro I wrote. I made a file .clj-kondo/metrics/histograms.clj with:
(ns metrics.histograms)

(defmacro defhistogram
  ([_registry histogram-name] `(defhistogram ~histogram-name))
  ([histogram-name] `(def ~histogram-name "histogram")))
Then added the following to .clj-kondo/config.edn
:hooks {:macroexpand {metrics.histograms/defhistogram metrics.histograms/defhistogram}}
But then when I run clj-kondo , I still see unresolved symbol:<metric name> . I tried the $ example in the docs and it worked. Do I need to do something special when I'm creating a replacement macro for a library I'm importing versus one in my own source tree?
#2023-07-2617:23sergey.shvetsHi, is there a way to ignore a specific form completely? I'm trying to disable linting for shadow.cljs.modern.defclass?#2023-07-2617:30borkdudeyes:
$ clj-kondo --lint - --config '{:config-in-call {shadow.cljs.modern/defclass {:ignore true}}}' <<< "(require '[shadow.cljs.modern :as m]) (m/defclass 1 2 x y z)"
linting took 39ms, errors: 0, warnings: 0
but for defclass you want at least the first symbol to act like a known var, so in this case:
{:lint-as {shadow.cljs.modern/defclass clj-kondo.lint-as/def-catch-all}}}
is a better fit
#2023-07-2617:39sergey.shvetsAMAZING! Thank you very much!#2023-07-3121:47Sam Ritchieasking here before I make an issue: Given a file test.clj
(ns test)

(defmacro defcake [& forms] `(defmacro ~@forms))
(defcake square [x] (if (:ns &env) `(* ~x ~x) `(/ ~x ~x)))
this command:
clj-kondo --lint test.clj --config '{:lint-as {test/defcake clojure.core/defmacro}}'
results in
test.clj:5:30: error: Unresolved symbol: &env
it seems that the :lint-as doesn’t handle the &env correctly
#2023-07-3121:50borkdudeissue welcome. a macro that calls defmacro isn't something I've seen a lot. for now use #_:clj-kondo/ignore on the &env form#2023-07-3121:57Sam Ritchiehttps://github.com/mentat-collective/emmy/blob/b7cd9be12f08772b450efcf621ce56e0cc869d9d/src/emmy/util.cljc#L141-L155#2023-07-3121:57Sam Ritchie@U050RLRRQ built a defmacro version that is sci copy-ns compatible#2023-07-3121:58Sam Ritchiehttps://github.com/clj-kondo/clj-kondo/issues/2149#2023-08-0202:44Chris McCormickI get Namespace name does not match filename for an ns called tests-e2e in an nbb file called tests-e2e.cljs . I understand the Clojure convention is tests_e2e.cljs but I frequently name my single-use top level nbb scripts in the dashed style. I wonder if it would make sense to support that as well?#2023-08-0204:53seancorfieldUsing a - is specifically an error for clj (jvm). Is it not an error for cljs as well? nbb allowing that seems... a bit of a footgun?#2023-08-0204:55borkdudeFor scripts you invoke from the command line it doesn’t matter, Clojure accepts it too, but clj-kondo doesn’t know the difference and I’d say jut avoid it or use an ignore hint. Footgun indeed#2023-08-0204:57seancorfieldFor scripts you invoke from the command line, you don't need an ns form anyway 🙂#2023-08-0205:10Chris McCormickWhy is it a footgun? What is the failure mode I should be worried about here?#2023-08-0205:11Chris McCormickWhat does :require look like without an ns form? I haven't seen that before.#2023-08-0205:15Chris McCormickAdding an ignore hint works well, thanks Michiel.#2023-08-0205:48seancorfieldJust use the require function directly?#2023-08-0207:58borkdude@UUSQUGUF3 The failure mode is when you add the same script to a project with a classpath. I personally just default to foo_bar.clj scripts#2023-08-0207:59andrea.crottiI was just hit by the fact that clj-kondo --lint src --fail-level=error is not the same as clj-kondo --lint src --fail-level error . Should it maybe not just fail with the = since it doesn't do what's expected?#2023-08-0208:00andrea.crottiit's probably standard for many commands to use the = , so I think maybe other people would do the same mistake?#2023-08-0208:04borkdudeyeah#2023-08-0208:04borkdudeissue welcome#2023-08-0208:05andrea.crottiok cool I can create one, or just try a PR if you agree it's a good idea#2023-08-0208:05andrea.crottiit should just error right? since I guess it's getting =error now maybe instead of error ?#2023-08-0208:05borkdudeissue first please#2023-08-0208:05andrea.crottiok np#2023-08-0208:06borkdudewe could maybe try to support the = syntax, if it's not too much hassle#2023-08-0208:06borkdudebabashka.cli supports it too#2023-08-0208:06andrea.crottiyeah that would be better maybe#2023-08-0208:06borkdudebut I don't know if migrating to babashka.cli will break things, I think it should do everything that clj-kondo needs#2023-08-0208:06borkdudebut I prefer minimal changes#2023-08-0208:07andrea.crottihttps://github.com/clj-kondo/clj-kondo/issues/2150#2023-08-0208:11andrea.crottiany idea why btw clj-kondo might not like requires like
["@blueprintjs/core" :refer [Button InputGroup Card Spinner Tag
                                         #_:clj-kondo/ignore
                                         Classes.FIXED
in a cljs file? It was marking Classes.FIXED as unused, and was also marking the Classes.FIXED in the file as unresolved symbols
#2023-08-0208:11andrea.crottiI guess it doesn't like the . ?#2023-08-0208:12borkdudeDoesn't CLJS support $ for this use case?#2023-08-0208:12borkdudeClasses$FIXED ?#2023-08-0208:12andrea.crottiah maybe I didn't know#2023-08-0208:12borkdudenot sure#2023-08-0208:13andrea.crottiit's not code I've written#2023-08-0208:13andrea.crottinot the most googlable thing#2023-08-0208:13andrea.crottibut I can try in the repl#2023-08-0208:15borkdudeas what do you refer this Classes.FIXED thing?#2023-08-0208:15borkdudeas FIXED?#2023-08-0208:16borkdude
cljs.user=> (require '["fs" :refer [readFileSync.foo]])
nil
cljs.user=> foo
            ⬆
WARNING: Use of undeclared Var cljs.user/foo at line 1
nil
cljs.user=> readFileSync
            ⬆
WARNING: Use of undeclared Var cljs.user/readFileSync at line 1
nil
🤷
#2023-08-0208:19borkdude
cljs.user=> (require '["fs" :refer [constants.O_RDONLY]])
nil
cljs.user=> O_RDONLY
            ⬆
WARNING: Use of undeclared Var cljs.user/O_RDONLY at line 1
nil
cljs.user=> constants
            ⬆
WARNING: Use of undeclared Var cljs.user/constants at line 1
nil
cljs.user=> constants.O_RDONLY
constants is not defined
#2023-08-0208:19borkdude🤷#2023-08-0213:14Stig Brautaset👋 We have some projects with a fairly well established pep8 -style scheme for sorting namespace requires & imports. Would there be any appetite for adding such a linter to clj-kondo? Or could we add a “local” linter rule for that?#2023-08-0213:16borkdudeI don't know what pep8 is but clj-kondo aligns with whatever clojure-sort-ns in emacs and clojure-lsp in whatever editor does. I think it's better to just take that as a standard to reduce fragmentation in the clojure tooling space#2023-08-0213:33Stig BrautasetPEP8 is a popular Python style guide, which says imports should be grouped in the following order: 1. Standard library imports. 2. Related third party imports. 3. Local application/library specific imports. This format is common where I work, but I’m entirely prepared to believe it’s an anomaly as I don’t have experience with Clojure elsewhere. The https://github.com/bbatsov/clojure-style-guide/pull/202, and many of our projects predate it. However, I totally appreciate that you don’t want to add rules for this to clj-kondo.#2023-08-0213:54borkdudeI'll keep it in mind for when more people ask for it, this is the first time that I've heard pep8 and clojure mentioned together :)#2023-08-0301:25hifumi123i personally just order my requires in lexicographical order. it may be possible to make a linter for my specific ordering, but the order being described above would be much tougher IMO e.g. if we decide to backport clojure.math to clojure versions below 1.11, clj-kondo would need to be aware of that somehow, as it is not part of the standard library there#2023-08-0301:26hifumi123(I guess one heuristic is to collect the :added metadata of each var then take the minimum or maximum, but I am not comfortable with this approach since anyone can introduce this metadata to their libraries and people regularly do so)#2023-08-0515:53Dustin GetzWhat process is auto generating this? Is it calva?#2023-08-0516:02borkdudeclojure-lsp by executing this:
clj-kondo --lint $(clojure -Spath) --dependencies --copy-configs --skip-lint
#2023-08-0516:02borkdudeCalva calls clojure-lsp and clojure-lsp calls kondo#2023-08-0516:02Dustin Getzdo I want this?#2023-08-0516:02Dustin Getzwe already have an exported config, i dont understand why this is happening#2023-08-0516:03Dustin Getzalso it has the wrong org name, it is com.hyperfiddle#2023-08-0516:03borkdudethat is your exported config#2023-08-0516:03borkdudeit's coming from here: https://github.com/hyperfiddle/electric/tree/master/resources/clj-kondo.exports/hyperfiddle/electric#2023-08-0516:03borkdudeit copies exported configs to the clj-kondo directory#2023-08-0516:04Dustin Getzare all prpjects supposed to gitignmore that directory?#2023-08-0516:04borkdudeyou can do it, but if you want all people to have the same experience without importing configs first, you can check them in as well. is this inside electric btw?#2023-08-0516:04Dustin Getzit's inside a demo repo#2023-08-0516:04Dustin Getzwhich depends on electric by submodule :local/root#2023-08-0516:04Dustin Getz(i dont trust tools to follow it correctly)#2023-08-0516:05borkdudeok, inside electric itself you can refer to the exported config so you don't have to duplicate the config in both places#2023-08-0516:05borkdudebut yes, this is expected behavior#2023-08-0516:05Dustin Getz> have the same experience without importing configs first what is "importing configs first"#2023-08-0516:06borkdudecalling
clj-kondo --lint $(clojure -Spath) --dependencies --copy-configs --skip-lint
imports the configs from the classpath. Please read https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration for more info. I'll be afk for a while
#2023-08-0516:15pezIn the projects I am involved in, I have so far always checked these configs in, fwiw.#2023-08-0516:16Dustin GetzThanks, yeah the design seems to be that projects should control the lint rules and inherit (by file copy) defaults from libraries#2023-08-0516:16Dustin Getz(It's not in the docs)#2023-08-0516:17Dustin GetzNot sure what happens if the library defaults change but projects have committed the stale rules#2023-08-0516:23borkdude@U09K620SG In that case, they are overwritten the next time you import#2023-08-0516:24Dustin Getzto be clear "you import" here means "open the folder in vscode" afaict#2023-08-0516:25borkdudewhat does "here" mean in "here means"?#2023-08-0516:26Dustin Getzmy experience of magic files showing up that i didn't ask for#2023-08-0516:26Dustin Getzi now understand what happened was i typed 'brew install clkj-kondo' at some point last week#2023-08-0516:26Dustin Getzi guess vscode was shelling out all along#2023-08-0516:26Dustin Getzsilently failing#2023-08-0516:26borkdudeyou can configure clojue-lsp to not import those files. clj-kondo never does this stuff on its own#2023-08-0516:27borkdudeclojure-lsp doesn't shell out to an external binary, it uses clj-kondo as a JVM library#2023-08-0516:27borkdudebut Calva does shell out to clojure-lsp as a binary#2023-08-0516:29borkdude> i now understand what happened was i typed 'brew install clkj-kondo' at some point last week clj-kondo never does anything automatically, I hate it when tools do things I didn't ask for too. but clojure-lsp does thing automatically. you can turn that off. Hope you have enough info now. There's also a #CPABC1H61 channel#2023-08-0516:33pez> I hate it when tools do things I didn’t ask for too Calva does a lot of things automatically. Some you can’t even configure it to stop doing. 😃#2023-08-0516:35Dustin Getzi think what happened was, presence of the global clj-kondo binary meant clojure-lsp (invoked by calva) suddenly succeeded after silently failing? causing the files to appear this week whereas i hadnt ever seen them before#2023-08-0516:35borkdudeno, the global binary is NOT used by clojure-lsp, so this is irrelevant#2023-08-0516:36Dustin Getzhmm ok must be my own confusion – i work in a couple dozen repos regularly#2023-08-0516:38pezclojure-lsp could have failed to start earlier even if it wasn’t related to the clj-kondo binary.#2023-08-0521:15lread@U09K620SG maybe to clear up confusion if it is not already clear: clojure-lsp uses clj-kondo as a library and tells that library to carry out certain tasks automatically.#2023-08-0521:17lreadMy humble take: I'm fine with these clj-kondo configs. I commit them to git. They improve linting support.#2023-08-0521:18borkdudeThanks for clarifying that @UE21H2HHD#2023-08-0523:44hifumi123I personally add the whole .clj-kondo to gitignore except for config.edn . It ends up looking like this
.clj-kondo/*
!.clj-kondo/config.edn
#2023-08-0523:45hifumi123The benefit behind this approach is that you can share linter configuration across a team while also ignoring any automatically generated stuff by clj-kondo#2023-08-0600:33lreadMy pref: the only thing I git ignore is the ./.clj-kondo/.cache, the rest gets committed.#2023-08-0600:34lreadBut ignoring everything but ./.clj-kondo/config.edn seems reasonable to me too.#2023-08-0523:49hifumi123How would I write a clj-kondo hook for a custom macro such that fully-qualified symbols do not emit warnings (and instead mark the namespace as used)? My use case involves a macro called lazyc, which I use to construct lazy components out of a Helix component. Due to the nature of shadow-cljs module loading, I cannot require the namespace in the file I call lazyc (otherwise I lose the ability to split code into lazily loaded modules) And on a similar note, how do people here debug their hooks?#2023-08-0608:47borkdudeCan you please give a concrete example how you invoke your macro?#2023-08-0608:47borkdudeTo debug, you can use println or develop from the REPL. This is all documented in the hooks.md docs#2023-08-0609:07hifumi123
(lazyc some.namespace/component)
#2023-08-0609:07hifumi123so in particular I believe I want to take rewrite-clj data, get an s-expression out of it, then somehow tell clj-kondo “I am expecting the second element to be a fully qualified symbol, please mark (namespace sym) as being referenced”#2023-08-0609:11borkdudeyou could just do:
{:config-in-call {your.ns/lazyc {:linters {:unresolved-namespace {:level :off}}}}}
#2023-08-0609:17hifumi123does this also work if i decide to ship this component in a library and specify an clj-kondo configuration file in the resource path?#2023-08-0609:20borkdudeyes, read the part about exporting configurations: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2023-08-0814:05hkjelsIf you use dot notation (.) for accessing methods within records, you lose the 'jump to symbol' capabilities, and clj-kondo will issue warnings about unused public variables. Is the idiomatic way to work with records to fully require all of its members? If that's the case, the require statements could grow considerably, leading to a more complex code structure 😞
#2023-08-0814:06borkdudeyou're never supposed to call methods on records via JVM interop, this is what protocol functions are for#2023-08-0814:07hkjelsOK. But you're also not suppose to use require all#2023-08-0814:07borkdudeI'm not sure what you mean, can you give an example?#2023-08-0814:10hkjelsWe have some protocols that are quite large. [ns :refer :all] would work fine, but I believe it's frowned upon by the greater community#2023-08-0814:11hkjelsit's probably fine for this situation specifically I guess#2023-08-0814:11borkdudeprobably just use a single letter alias?#2023-08-0814:12hkjelsor that of course :face_with_peeking_eye:#2023-08-0814:13hkjelsthanks. I have a rewrite to do#2023-08-0814:13borkdudegood luck :)#2023-08-0915:48Jake PearsonHi. I continue to work on getting all the lints out of my team's repos this week. I got to a bunch of unresolved symbols due to our usage of hugsql. I found @borkdude response on https://stackoverflow.com/questions/61727582/how-to-avoid-unresolved-symbol-with-clj-kond-when-using-hugsql-def-db-fns-macro, but wondered if a more automatic solution would be possible. I wrote the following code (that appears to do what I want from my REPL):
(ns hugsql
  (:require [clojure.string :as string]))

(defn def-names [resource-path]
  (let [lines (-> (str "src/" resource-path)
                  clojure.core/slurp
                  string/split-lines)]
    (->> lines
         (filter (fn [line]
                   (string/starts-with? line "-- :name")))
         (map (fn [line]
                (-> line
                    (string/split #" ")
                    (nth 2)))))))

(defmacro def-db-fns [file _options]
  (->> (for [defn-name (def-names file)]
         `(defn ~defn-name [db arg-map]))
       (cons 'do)))
And mapped it in my clj-kondo config. I now get the following output in clj-kondo:
WARNING: error while trying to read hook for hugsql.core/def-db-fns: Could not resolve symbol: clojure.core/slurp
Is there a way to read a file using the SCI parser that clj-kondo uses?
#2023-08-0915:59Stig BrautasetWe put this bit in a separate “queries” namespace:
(hugsql/def-db-fns "select_things.sql")
The indirection means that clj-kondo doesn’t complain.
#2023-08-0915:59Stig BrautasetAnd we don’t have to put declare anywhere.#2023-08-0916:00Jake PearsonOk! I can do that.#2023-08-0916:01Jake PearsonThanks. Let me give that a try.#2023-08-0916:09Jake PearsonHmm, I think I did what you suggested, but I still get a lint:
src/voltron/queries/db.clj:17:4: warning: Unresolved var: queries/select-stuff
changed from unresolved symbol to unresolved var. Did you make any other changes?
#2023-08-0916:12Stig BrautasetNo, I don’t think so. I don’t see any exclusions in our config file.#2023-08-0916:13Jake PearsonI'll try making a little repo and see if I can get it to work.#2023-08-0916:13Jake PearsonThanks#2023-08-0916:42borkdudeYou can get rid off those unresolved-var stuffs by adding a bit more config:
{:linters {:unresolved-var {:exclude [the-hug-sql-vars.ns]}}}
#2023-08-0916:44Jake Pearson@U03N9E40Q2F On my trivial example project, your suggestion worked. Something must be a little different in my real repo.#2023-08-0916:44Stig BrautasetOlder version of clj-kondo?#2023-08-0916:44Jake Pearson
clj-kondo v2023.07.13
#2023-08-0916:44borkdudeThe difference comes from having a non-empty .cache entry for that namespace or not#2023-08-0916:45Jake PearsonThat makes sense. Thanks.#2023-08-0916:45borkdudeif there is a non-empty one, then clj-kondo thinks its knows that namespace and will start to warn about that namespace#2023-08-0916:47Jake PearsonI deleted my cache and the warning went away. Thanks everyone for the help. And @borkdude for the great tool.#2023-08-1015:01Jake PearsonI think everything is working now, but I was still wondering if there is a way to read in a file in the interpreter that kondo uses?#2023-08-1015:04borkdudewhat would be the use case for this?#2023-08-1015:07Jake PearsonThe thing I can think of would be the example I wrote at the top of this thread. Hugsql reads in a file to generate defs so I would love to get the same functionality instead of excluding a namespace from some lints.#2023-08-1015:08borkdudeare you using clojure-lsp perhaps?#2023-08-1015:09Jake PearsonI use lsp through calva, but for PR checks we use clj-kondo from the command line.#2023-08-1015:10borkdudeok. for clojure-lsp you could use stubs: https://clojure-lsp.io/settings/#stub-generation it uses this little library: https://github.com/clj-easy/stub you could just create some stubs manually and add that to a :clj-kondo alias in your deps.edn and add it to the lint classpath#2023-08-1015:10borkdudethis would probably be an easier route than trying to parse .sql files in a clj-kondo hook#2023-08-1015:10Jake PearsonThanks, I'll take a look#2023-08-0921:18JoelSeems like a leading hyphen in a function name as in -my-function is very common to denote a “private” function. Is there a Kondo check for misuse? (Invoking the function from another namespace)#2023-08-0921:20borkdudeif the function is private, you should use the ^:private metadata. - does not always mean private, e.g. -main is a common convention#2023-08-0921:24JoelYeah, I knew it wasn’t “canon”, but I see it a lot, I suppose to avoid the extra referencing in the tests.#2023-08-0921:28seancorfieldIn particular -main uses a - to indicate that it should be compiled to a Java main function -- so you'll see a leading hyphen in any code that is gen-class'd for producing Java-compatible methods.#2023-08-0921:31borkdude- is also a convention in ClojureScript protocols, it doesn't necessarily mean private. it could mean "lower level function" but it was specifically NOT made private, because other namespaces (of the same library) sometimes need to call into those lower level functions#2023-08-1023:31hifumi123heh, borkdude beat me to it. My immediate instinct on the comment about - prefixes was to bring up specifically naming conventions in ClojureScript protocol functions, and the fact that it is the default prefix when you use :gen-class in JVM Clojure. 🙂#2023-08-1023:32hifumi123With that said, in the CLJS world -foo typically points to an implementation detail. It may be useful to write a linter that warns on this prefix, but enabling it by default would not be a good idea, and it is not very useful at all in JVM Clojure#2023-08-1005:12John Doebeginner question: When I tried to change a var in some library, for example (alter-var-root #'cheshire.parse/*use-bigdecimals?* (constantly true)) clj-kondo complains Unresolved namespace cheshire.parse. Are you missing a require? . Do I actully need to add a require cheshire.parse to suppress the warning, or is this just a false positive warning to ignore?#2023-08-1005:59jumarYes, in clojure you need to require a namespace before using its vars#2023-08-1006:04John DoeIf I just create a new empty ns without any require and run the code , it just runs and changes the global var from that library. Is this expected?#2023-08-1007:41delaguardoyou can use qualified vars without requiring the namespace but only if the corresponding namespace was loaded (for example requered transitively). but it is always better to be explicit and require in the namespace that uses that var#2023-08-1007:54John DoeThanks for the explanation. I do have a http client which has a {:as :json} which requires cheshire transitively I guess. Is there a way to list all namespaces being required transitively so I can verify this case?#2023-08-1007:59jumarYou can use :verbose with require https://clojuredocs.org/clojure.core/require#2023-08-1008:03John DoeAhh, thanks again! I can see where it's loaded now. Much appreciated!#2023-08-1506:16kwisathI updated to version v2023.07.13 and now clj-kondo still works perfectly fine when I start my emacs, but as soon as I perform a modification to the file and save it, I get a Could not process file. error at position 0:0 and all the linting of the file disappears. If I open a new file on the project, the same happens, works perfectly until a save is made. Does anybody had this issue? Any ideas on how to troubleshoot that? I also updated to the latest clojure-lsp at the same time, so it may be related to that. In fact, if I disable the lsp on the buffer that was complaining with Could not process file. , then clj-kondo works again.#2023-08-1506:49borkdudeCan you try clj-kondo from the command line?#2023-08-1506:50kwisathsure#2023-08-1506:50kwisathI guess is clj-kondo and then the name of the file?#2023-08-1506:53kwisathOk, on the command line it works. Which I guess it was the expected thing, as when I disable clojure-lsp it works fine#2023-08-1506:55borkdudeWhat happens if you enable LSP and disable kondo?#2023-08-1506:55kwisathchecking#2023-08-1507:00kwisathmmm... strange. I am using spacemacs and I just removed from the configuration the clojure-enable-linters 'clj-kondo but when I reopen emacs, the behavior is the same clj-kondo seems to be still running#2023-08-1507:02kwisathwhen I asked the version on clojure-lsp, it showed me this
clojure-lsp 2023.08.06-00.28.06
clj-kondo 2023.07.14-SNAPSHOT
although when I ask the version of clj-kondo on my CLI I get clj-kondo v2023.07.13
#2023-08-1507:03kwisathIs clojure-lsp packing its own version of clj-kondo?#2023-08-1507:28kwisathyes, I read that is indeed the case. I managed to disable clj-kondo on lsp by
{:linters {:clj-kondo {:level :off}}}
but then all linting is gone.
#2023-08-1507:58borkdudeclojure-lsp uses clj-kondo#2023-08-1507:58borkdudeso when you use clojure-lsp, you automatically get clj-kondo#2023-08-1522:26kwisathI recover this discussion since I was finally able, after a laborious investigation, to hunt down the problem to a particular option in the config.edn file#2023-08-1522:27kwisath
cat config.edn 
{ :exclude-files ["tester/results"]}
#2023-08-1522:28kwisaththat single line is what is causing all the problems#2023-08-1522:29kwisathany idea on what this may be failing on version 2023.07.14-SNAPSHOT while it was working in a previous version?#2023-08-1522:30kwisath(just in case you were wondering, it fails both if the given folder "tester/results" exists or not)#2023-08-1510:41robert-stuttafordwhat is the correct syntax for adding an exclusion to https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#deprecated-namespace ? this doesn't seem to be working:
{:exclude [hiccup.core]}
#2023-08-1510:42borkdudeif the linters.md doc doesn't give one, it's not implemented. you can just use a #_:clj-kondo/ignore there and/or submit an issue if this isn't sufficient#2023-08-1510:43robert-stuttafordok, will sub an issue; the ns is in a lib, so the only control plane is the top-level config#2023-08-1510:43robert-stuttafordthank you#2023-08-1510:45borkdudewhy do you care about lint warnings from a lib#2023-08-1510:46borkdudeyou should not care about those if the source is not under your control#2023-08-1510:47robert-stuttafordwe're requiring a deprecated ns from a library in a ton of places. it'd be better to put one exclude in the config, than to pepper a bunch of ignores all over the place 🙂 ... unless that's our only option, in which case, that's what we'll do, hehe#2023-08-1510:48borkdudeok, so the warning does come from usage in your own source, rather than usage in someone elses lib. makes sense now#2023-08-1510:48robert-stuttafordyes#2023-08-1510:48borkduderight now that's your only option. the namespace is deprecated for a reason. why don't use you use hiccup2.core#2023-08-1510:48borkdudebut I'll implement the issue hopefully on the next release#2023-08-1510:48robert-stuttafordlegacy code, no appetite to switch and retest everything#2023-08-1510:49robert-stuttaforddrawbacks to maintaining code for over a decade, hehe#2023-08-1510:49borkdudeanother workaround for the meanwhile is to wrap hiccup.core in your own ns and only apply the ignore hint in your own ns#2023-08-1510:49robert-stuttafordthank heavens for clojure#2023-08-1510:49robert-stuttafordyep#2023-08-1510:50borkdudeor just switch off the deprecated ns linter until the next release#2023-08-1510:52robert-stuttafordthank you, borkman 🙂 appreciate your stuff as always!#2023-08-1612:20teodorlu
(str/starts-with? 'clojure "clojure")
;; => true
This code runs, but I get a [type-mismatch] lint message from clojure-lsp, and I’m assuming the message comes from CLJ-kondo. Is it bad to use clojure.string/start-with? with symbols without explicitly converting to strings first? If yes, why?
#2023-08-1612:22borkdudeYes, you're relying on an implementation detail. See the source:
(defn starts-with?
  "True if s starts with substr."
  {:added "1.8"}
  [^CharSequence s ^String substr]
  (.startsWith (.toString s) substr))
The argument s is a CharSequence
(instance? CharSequence 'foo)
false
#2023-08-1612:24borkdudeI guess if the type hint would have been Object then the function would still have worked, but I'm not sure if the intent is that you're throwing random objects in there. Perhaps better to ask @U064X3EF3#2023-08-1612:24teodorluDoes that I will get better performance too with an explicit call to str, because I can avoid reflection?#2023-08-1612:24teodorlu(Just listened to Alex’s London Clojurians talk about Clojure performance, was really interesting)#2023-08-1612:25borkdudeWell, there isn't any reflection going on, I guess .toString is just resolved to Object's toString. It's a strange edge case#2023-08-1612:26teodorluI tried testing quickly, added (set! *warn-on-reflection* true) to the top of my ns, didn’t get any warnings.#2023-08-1612:27teodorluThanks for the help! 🙏#2023-08-1612:48Alex Miller (Clojure team)The intent here is that you pass it a CharSequence like a String#2023-08-1612:49Alex Miller (Clojure team)The toString is necessary because not all CharSequences are Strings #2023-08-1612:49Alex Miller (Clojure team)Not sure if that answers your question #2023-08-1612:50borkdudeyep, that's how I understand it too. so throwing in a symbol isn't the intent, hence the clj-kondo warning is legit#2023-08-1613:09teodorlu> Not sure if that answers your question It does! 🙏#2023-08-1705:55d5phi, is there an option to have kondo to regenerate its cache each time it runs? we execute with a lein alias similar to ["run" "-m" "clj-kondo.main" "--lint" "src/clj"] , just spent a while dealing with a difference between environments and it was the .clj-kondo/.cache on one of them that was much older so had been around across multiple kondo versions and was causing mismatches in behaviour , we can wire up a shell command to clear it but was wondering if there was a kondo option#2023-08-1706:06d5pahh found the --cache option, all good 🙂#2023-08-1819:13tomdWhat do folks think of a linter for non-double-wrapped anonymous function forms in thread-first constructs? I expect it's so rare that anyone wants to thread a value into the name slot of a function that it can safely be a lint error (maybe optional). Got the idea from a question in #beginners just now. E.g.
(-> foo (fn [x] (bar x)))
I'd wager no one has ever done this on purpose.
#2023-08-1819:25Noah Bogarti'd use that#2023-08-1819:27tomdAs in, you'd use the linter, or you'd use that syntax purposefully (I assume the former 😅 )#2023-08-1819:27Noah Bogarthaha the linter#2023-08-1819:27Noah Bogartit took me a while to get used to (-> ... (#(...)))#2023-08-1819:27tomdYeah likewise#2023-08-2117:23tomdfwiw, I made an issue and linked a PR, here: https://github.com/clj-kondo/clj-kondo/issues/2159#2023-08-2016:26Ronny LiHi folks, does anyone know the correct ordering for the following namespaces? I keep getting Unsorted namespace and I feel like I tried every possible combination
[ :as io]
   [clojure-csv.core :as csv]
   [clojure.string :as string]
#2023-08-2016:33skynetthe - will be sorted before/after the . (I forget which, try both)#2023-08-2017:40borkdude
(ns babashka.dude
  (:require [clojure-csv.core :as csv]
            [ :as io]
            [clojure.string :as string]))
#2023-08-2018:01Ronny LiThanks everyone, unfortunately still seeing Unsorted namespace: clojure-csv.core#2023-08-2018:04borkdudethis is because environ.core goes after clojure.*#2023-08-2018:05borkdudeif you use cljfmt it will format this for you automatically#2023-08-2018:05Ronny Lioh geez that's so embarrassing. Thank you!#2023-08-2018:06borkdudeno problem :)#2023-08-2121:06Nick McAvoyI'm seeing a false positive with a java import in the clj reader conditional of a babashka file. It's showing unused. (See thread.)#2023-08-2121:06Nick McAvoyHere's asdf.cljc
(ns asdf
  (:import
   (java.math BigDecimal)))

#?(:clj
   (do
     (defn ->decimal
       (^BigDecimal
        [value]
        (if (string? value)
          (BigDecimal. ^String value)
          (bigdec value))))))
#2023-08-2121:06Nick McAvoy
> clj-kondo --lint /tmp/asdf/asdf.cljc 
/tmp/asdf/asdf.cljc:3:15: warning: Unused import BigDecimal
linting took 11ms, errors: 0, warnings: 1
#2023-08-2121:06Nick McAvoy
> clj-kondo --version
clj-kondo v2023.07.13
#2023-08-2121:07Nick McAvoyI'm happy to file an issue, just configure this one away, or whatever you recommend.#2023-08-2121:10borkdudeThis is because the :import is not in a :clj reader conditional. It won't work in CLJS anyway#2023-08-2121:34Noah BogartBut also, babashka files use the clj branch of the bb branch isn’t encountered first#2023-08-2121:34Noah Bogart(Hi @U01BA210C7K !)#2023-08-2121:40Nick McAvoyYo Noah!#2023-08-2121:40Nick McAvoyYes, we have this in our source code here:
#?(:clj ;; bb will load :clj code if no :bb implementation is defined. The following code is compatible with clj and bb, but not cljs.
We've got bb and clj in our stack, but not cljs, so cljs incompatibility is not a problem for us.
#2023-08-2121:41borkdudeAlright, you can put this in your config.edn: {:cljc {:features [:clj]}}#2023-08-2121:42borkdudethen clj-kondo will only lint the :clj branches and won't complain about anything related to other stuff#2023-08-2121:42borkdudein your above repro, the :clj branch will still be executed by bb as well btw.#2023-08-2121:43borkdude(but you already knew this, I got this from your latest reaction)#2023-08-2121:45Nick McAvoyI'll try that, thank you!#2023-08-2121:50Nick McAvoyYup, the warnings disappeared. Thanks again!#2023-08-2213:58fuadHi! I recently found myself in a situation where I'd like to have some deftest calls inside of a let : the namespace contains a huge number of tests and I want to create some local bindings that only apply to a handful of them. Doing deftest inside of a let throws clj-kondo off, raising a "unused value" problem for all deftests except for the last one. I tried addressing this by telling kondo to resolve deftest as def (since the linter does not complain about def ) but that didn't have any effect. A few questions: • is the unused-value behavior for deftest expected? • if so, should resolving deftest as def be a reasonable way to address it?#2023-08-2214:14borkdudedeftest + unused value was fixed recently, are you using the newest clj-kondo version?#2023-08-2214:21fuadI believe it is the latest version
~/S/e/ellipsus-service ❯❯❯ clj-kondo --version
clj-kondo v2023.07.13
I also observe the same behavior with kondo over lsp:
~/.l/s/n/m/bin ❯❯❯ ./clojure-lsp --version
clojure-lsp 2023.08.06-00.33.37-nightly
clj-kondo 2023.07.14-SNAPSHOT
#2023-08-2214:23borkdudeand can you make a full standalone but minimal repro (code)?#2023-08-2214:30fuadsure!#2023-08-2214:30fuadshould I submit an issue?#2023-08-2214:34borkdudeyeah, makes sense. you can suppress this for now with:
(ns deftest
  (:require
   [clojure.test :refer [deftest is]]))

#_{:clj-kondo/ignore [:unused-value]}
(let [some-var "some-value"]
  (deftest this-one-is-flagged-as-unused
    (is (= some-var "some-value")))
  (deftest this-one-is-fine
    (is (= some-var "some-value"))))
#2023-08-2214:35fuadyes! that's what I've done. I also tried the namespace level ignore but to no avail:
(ns deftest-unused-val-repro
  {:clj-kondo/ignore [:unused-val]}

  (:require
    [clojure.test :refer [deftest is]]))

(let [some-var "some-value"]
  (deftest this-one-is-flagged-as-unused
    (is (= some-var "some-value")))

  (deftest this-one-is-fine
    (is (= some-var "some-value"))))
#2023-08-2214:36borkdude:unused-value , not :unused-val#2023-08-2214:37borkdudebut yeah that still doesn't work#2023-08-2214:37fuadyeah, I also tried :config-in-ns#2023-08-2214:39fuadignore works for other linters without any issue, so I'm assuming it's something specific to :unused-value#2023-08-2214:40borkdudeyep, also mention this in the issue, or make a separate issue about it#2023-08-2214:50fuadI included a comment in the same one as it seems related to the original problem as opposed to a completely separate problem (although I'm not familiar enough with kondo's internals to rule that out).#2023-08-2214:53borkdudeok#2023-08-2215:59Nick McAvoyWe use some macros from clojure.algo.monads. I'm currently looking at usage of domonad, which has two arities
Usage: (domonad steps expr)
       (domonad name steps expr)
We currently have this linting as clojure.core/loop, but loop matches the first arity, and not the second. Is there an "easy" answer here, apart from finding another macro with the same semantics, or writing the config custom?
#2023-08-2216:02borkdudeno easy answer, other than: ignoring lint warnings completely or to write a hook for it#2023-08-2216:03borkdudeprobably a hook would not be so difficult, you just expand into a loop expression and let the name drop#2023-08-2216:03Nick McAvoyThat sounds worth trying#2023-08-2301:00Nick McAvoyThis alone took care of 10% of our total warnings!
(defn- domonad-helper
  ;; This arity of domonad takes a name,
  ;; but for the purposes of linting,
  ;; we can just throw that out.
  ([domonad _ steps expr]
   (domonad-helper domonad steps expr))
  ([_ steps expr]
   {:node
    (api/list-node
     (list
      (api/token-node 'let)
      steps
      expr))}))

(defn domonad [{{children :children} :node}]
  (apply domonad-helper children))
#2023-08-2301:35Nick McAvoy..Though I just learned my assumption that name was unimportant was incorrect. It should be a token that exists, and is usually from another ns. So now I have many fewer warnings overall, but some false positive "referred but never used" warnings where the name parameter above had been referred, and this is the only place it's used.#2023-08-2307:32borkdudeThen you can just emit a usage of that name?#2023-08-2314:32Nick McAvoyThat sounds right. Can you please point me in the direction of how to do that? I just spent a bit of time but didn't turn it up.#2023-08-2314:35borkdudeJust insert it between steps and expr maybe ?#2023-08-2314:51Nick McAvoyIt was as simple as that. Thank you again!
(defn- domonad-helper
  ([_ steps expr]
   (list
    (api/token-node 'let)
    steps
    expr))
  ([_ name steps expr]
   (list
    (api/token-node 'let)
    steps
    name
    expr)))

(defn domonad [{{children :children} :node}]
  {:node (api/list-node (apply domonad-helper children))})
#2023-08-2410:00pithyless
Unexpected error. Please report an issue.
java.lang.IllegalArgumentException: no conversion to symbol
Is there a way I can get more info on where clj-kondo failed during parsing (to help produce a minimal repro)?
#2023-08-2410:01borkdudeTry CLJ_KONDO_DEV=true ...#2023-08-2410:01pithylessI found https://github.com/clj-kondo/clj-kondo/issues/1670 But I don't think it's the same, since I'm testing with 2023.07.13#2023-08-2410:02borkdudePerhaps this is a configuration issue#2023-08-2410:08pithylessbingo!#2023-08-2410:09pithylessconfig had:
:unresolved-symbol {:exclude [(symbol.without.slash [symbols ...])]}
#2023-08-2410:09borkdudefeel free to post an issue so clj-kondo can handle this better#2023-08-2410:41pithylesshttps://github.com/clj-kondo/clj-kondo/issues/2167#2023-08-2410:42pithylessThanks @U04V15CAJ for quickly pointing me to the probable cause!#2023-08-2410:43borkdude👍#2023-08-2410:23Stig Brautaset Our coding guidelines allows calling private functions (with #') from tests, but disallow it otherwise. Our solution so far has been to run clj-kondo twice: one for “src”, and again for test: clj-kondo --config '{:linters {:private-call {:level :off}}}' --lint test . I’m wondering if there’s any appetite for a config option (and whether it’s even possible) to make the :private-call linter take a path ignore files?#2023-08-2410:23Stig BrautasetI’m thinking something like {:linters {:private-call {:ignore-paths ["test"]}} in config.#2023-08-2410:24Stig BrautasetI’m also open to being told it’s a terrible idea 🙂#2023-08-2410:27borkdudeThis is what the :config-in-ns option is for, no need to implement this for each linter specifically#2023-08-2410:27borkdudethe private-call linter won't report #'foo calls anyway btw#2023-08-2410:46Stig BrautasetThat is contrary to my experience, where the private-call linter does report for #'foo. I just tried it again. However, :ns-groups and :config-in-ns looks like they have my back — if I can only get the syntax right 🙂#2023-08-2410:52borkdude
$ clj-kondo --lint - <<< "(ns foo) (defn- foo []) foo (ns dude (:require [foo])) (#'foo/foo)"
linting took 12ms, errors: 0, warnings: 0
#2023-08-2410:52borkdudevs.
$ clj-kondo --lint - <<< "(ns foo) (defn- foo []) foo (ns dude (:require [foo])) (foo/foo)"
<stdin>:1:56: error: #'foo/foo is private
#2023-08-2410:55Stig BrautasetHow curious! I can reproduce that, but that is not the behaviour I’m seeing in our projects.#2023-08-2410:56borkdudecounter-repro welcome#2023-08-2410:56Stig Brautasetme experiments more#2023-08-2411:09Stig BrautasetAha, I think I have been tricked by the error clj-kondo prints. This is error: #'foo/now is private — but the actual code is:
(bond/with-stub! [[foo/now (constantly #inst "2017-03-30T20:52:03.690-00:00")]
(`bond` is a stubbing library.)
#2023-08-2411:10Stig BrautasetNevertheless, ns-groups and config-in-ns seems like it should work for me here.#2023-08-2411:11borkduderight#2023-08-2411:12borkdudeif bond/with-stub! is supported via a hook, you can maybe update the hook to suppress the private-call warning#2023-08-2411:17Stig BrautasetI’m not sure what “supported via a hook” means, I’m afraid, though that sounds interesting. The source is here: https://github.com/circleci/bond/blob/main/src/bond/james.clj#L96-L105#2023-08-2411:17Stig Brautaset… though I’ve now managed to get the :config-in-ns option to work, which is a massive improvement on what we have#2023-08-2411:20borkdude> I’m afraid, though that sounds interesting Fear not :) What I mean is, did you do anything to configure this macro to not cause any lint warnings?#2023-08-2411:20borkdudeYou can also configure it like:
{:config-in-call {foo.bar/bond {:linters {:private-call {:level :off}}}}}
#2023-08-2411:28Stig BrautasetMmm! That’s perhaps even better here. Nice and narrow.#2023-08-2411:29Stig BrautasetThank you!#2023-08-2515:07zimabluestupid question, is there an intended way to make clj-kondo run continuously? so that each file change updates an output? run! seems to run once and return a map, maybe storing the info in the cache also (?)#2023-08-2515:08borkdudeI'm not exactly sure what your use case is, please elaborate#2023-08-2515:13zimablueso that if I modify code in a file and save (or not?) I can automatically access an updated analysis output#2023-08-2515:14borkdudeclj-kondo is a too low level component for this, you need a file watcher and combine it with a call to clj-kondo#2023-08-2515:14zimablueI thought that might be the case just wasn't sure#2023-08-2515:14zimabluethank you#2023-08-2515:14borkdudelike clojure-lsp for example does#2023-08-2515:15zimabluedoes this mean kondo always goes through a pass of writing/parsing from the filesystem to handle a change? is that significant performance-wise?#2023-08-2515:16borkdudeit does#2023-08-2515:16borkdudeI don't know if this is a performance bottleneck, I don't think so#2023-08-2515:17zimabluethanks a lot for your help#2023-08-2515:18zimablueI guess some bits that would often live in an IDE but in an adhoc way to assist me with my project#2023-08-2515:18zimablueand glueing together open source things mostly#2023-08-2515:18borkdudemakes sense#2023-08-2711:21vemvI'm curious, can clj-kondo possibly make use of node_modules to improve its analysis?#2023-08-2719:25EdI wonder if LSP has some kind of cross language part, so you could lean on the js LSP server for interop calls?#2023-08-2720:51Edhttps://github.com/microsoft/language-server-protocol/issues/107 ... oh... I guess not?#2023-08-2809:41borkdudecan you give an example of a use case of improved analysis? we have java-parser to improve java analysis, maybe something similar exists for js, but on the other hand, I hope to keep clj-kondo a bit lean#2023-08-2814:21vemvIt's not too hard to imagine use cases (arity / type checking, enhanced info for LSP-like features) however the question was simply curiosity. I don't always work with cljs, so I may miss out on what the state of the art is for every tool.#2023-08-2814:24borkdudeI think it's possible. Currently the java analysis in clj-kondo doesn't even take advantage of arity checking which is probably more low hanging fruit#2023-08-2917:39John Doeanybody know what's the proper syntax to lint-as def :^dynamic {:lint-as {xxx.core/mydef clojure.core/def}}, here I dont want a normal def, but a dynamic def#2023-08-2917:45borkdudehow does the problem manifest itself when you use the above config?#2023-08-2917:46John Doeso I'm defining my weird def to lint as normal def, but since I use my-weird-def with earmuffed name always, so I'm actully defining my-weird-def as def :^dynamic, hope that make sense:slightly_smiling_face:#2023-08-2917:47borkdudecan you please give an example/repro of what code goes in and what undesired warnings come out?#2023-08-2917:50John Doesure, take this repo for example: https://github.com/teknql/systemic it has {:lint-as {systemic.core/defsys clojure.core/def}} , but from usage example its defsys all have earmuffed name. clj-kondo [earmuffed-var-not-dynamic]: Var has earmuffed name but is not declared dynamic: server#2023-08-2917:51John Doeso this case I guess it'd be more proper to lint systemic.core/defsys as def :^dynamic i guess#2023-08-2917:51borkdudeI can't reproduce:
$ clj-kondo --config '{:lint-as {foo/deffoo clojure.core/def}}' --lint - <<< "(ns foo) (declare deffoo)  (deffoo ^:dynamic *foo* 1)"
linting took 5ms, errors: 0, warnings: 0
#2023-08-2917:52hiredmanor, if don't want to be warned for defining names with earmuffs that are not dynamic, turn off the linter that does that#2023-08-2917:52borkdudedo you mean that deffoo always creates a dynamic var?#2023-08-2917:52John Doeyeah, turing that off is another way 😄#2023-08-2917:52John Doeyes, deffoo always creates a dynamic var#2023-08-2917:54borkdude@U0599HVJX70
$ clj-kondo --config '{:config-in-call {foo/deffoo {:linters {:earmuffed-var-not-dynamic {:level :off}}}} :lint-as {foo/deffoo clojure.core/def}}' --lint - <<< "(ns foo) (declare deffoo)  (deffoo *foo* 1)"
linting took 58ms, errors: 0, warnings: 0
#2023-08-2917:54borkdude:config-in-call lets you disable this linter only in calls to your macro, see above#2023-08-2917:56hiredmanin the example code above it is not the case that defsys creates a dynamic var#2023-08-2917:57hiredmanyou can tell because you can grep the code base for :dynamic and Dynamic#2023-08-2917:57John Doeyeah, i know, i happen to like its convention of earmuffed name this case, nothing about dynamic or not this case#2023-08-2917:58John Doethanks @U04V15CAJ, that works!#2023-08-3120:10skynetit seems there is no linting for throw so for example forgetting to do ex-info like:
(throw "message" {:data 1})
clj-kondo gives no warnings. it's minor though since it'll fail pretty fast
#2023-08-3120:11borkdudeissue welcome#2023-08-3120:11borkdudeI think we could implement it via the type checking system#2023-08-3120:14skynetcool, will try to open one later today#2023-09-0101:29skynetopened it here https://github.com/clj-kondo/clj-kondo/issues/2172#2023-09-0215:28skynetfixed so fast! thanks!#2023-08-3121:19dpsuttonJust wrote my first hook. Lovely setup. Thanks for a great system. Also, big fan of the documentation. The documentation has a great demo of how to work with these hook files that aren’t on the classpath. I found the following to be particularly helpful:
(comment
  (def input (hooks/parse-string
              "(with-indexed-model [{:keys [model model-index model-index-value]}
                                    {:query :some-query}]
                  :foo :bar :body)"))

  (println (hooks/sexpr input))

  (let [f (load-file ".clj-kondo/hooks/path_to_hook.clj")]
    (f {:node input})))
and if you save the (let [f (load-file …)] (f {:node input})) form to a register, it makes it super simple to send that form to the repl and evaluate it. Many thanks to everyone who helped design and implement hooks!
#2023-08-3121:20dpsuttoni just left this comment form in the file that defines the hook. makes it easy to keep the hook updated if a macro’s syntax ever changes. Sample call, load the file and process your hook. Relies on the fact that the hook is the last var in the namespace you are loading. If that’s not the case, just use a fully qualified name for f and just load the file without grabbing its return value#2023-09-0605:43SebastianIs there anyway to access type information (if any) when using hooks? Let's say I have
(let [x 1
      y 1.0]
  (my-lib/my-func x y))
In this case, x is an int and y is a double. I can see, that I can do https://github.com/clj-kondo/clj-kondo/blob/master/doc/types.md, but what if I want to give a warning, if x and y is not either both ints or doubles? Is there anyway to achieve that? Also, thanks for the great tool and documentation 😇
#2023-09-0608:45borkdudeThis isn't possible with normal hooks as the types aren't fully known at that stage. Perhaps we can invent a new hook which gets invoked with the types or so, but it's currently not there#2023-09-0609:04SebastianFair enough. Thank you for the clarification. 👌#2023-09-0610:02SebastianI've been messing a bit around with clj-kondo hooks and experienced the following error: WARNING: error while trying to read hook for my-lib/my-func: Could not resolve symbol: api/set-node From reading the source, my best guess is, that api/set-node is missing from api-ns. My best guess would be, that all public functions in hooks-api should be exposed here, which seems to be easy to do (https://github.com/clj-kondo/clj-kondo/commit/830f5913c62716e9612b8ff800d66896a7de71d7). But it seems that functions such as walk is actually internal and should not necessarily be exposed?#2023-09-0610:04borkdudeCorrect#2023-09-0610:05borkdudePR welcome#2023-09-0610:05borkdudeexcluding those internal functions#2023-09-0610:05borkdudefor now you can use (api/coerce #{1 2 3})#2023-09-0610:07SebastianShould I make the functions private or just exclude them from the test?#2023-09-0610:12borkdudeI'll answer later, gotta go wnow#2023-09-0610:36SebastianSure, no stress :person_in_lotus_position:#2023-09-0613:29borkdudeI committed something to master. Didn't expose everything, but almost everything#2023-09-0613:29borkdudecan you check? I was going to do a release today#2023-09-0615:13SebastianYes, it seems to do the job 👏 Thanks!#2023-09-0619:12borkdudehttps://clojurians.slack.com/archives/C06MAR553/p1694027506061099#2023-09-0620:11skynet@U04V15CAJ there seems to be false positives from the new linter related to reader conditionals:
$ clj-kondo --version
clj-kondo v2023.09.07

$ cat .clj-kondo/config.edn
{:linters
 {:unused-alias {:level :warn}}}

$ cat src/alias_issue.cljc
(ns alias-issue
  (:require
    #?@(:cljs [["dayjs" :as dayjs]
               ["dayjs/plugin/utc" :as dayjs-utc]])))

#?(:cljs
    (.extend dayjs dayjs-utc))

$ clj-kondo --lint src/alias_issue.cljc
src/alias_issue.cljc:3:29: warn: Unused alias: dayjs
src/alias_issue.cljc:4:40: warn: Unused alias: dayjs-utc
linting took 9ms, errors: 0, warnings: 0
#2023-09-0620:14borkdudeNot sure if this is a false positive, the warning appears because you're not using the alias in one language or the other.#2023-09-0620:17borkdudeor wait, you're only defining + using it in cljs right?#2023-09-0620:18borkdudeAh, I think this is a specific CLJS false positive: the alias can be used as an object itself. So I don't think it's related to reader conditionals#2023-09-0620:20borkdudeThis is a shorter repro:
$ clj -M:clj-kondo/dev --lang cljs --config '{:linters {:unused-alias {:level :warn}}}' --lint - <<< '(ns foo (:require ["dayjs" :as dayjs])) dayjs'
<stdin>:1:32: warn: Unused alias: dayjs
linting took 50ms, errors: 0, warnings: 0
#2023-09-0620:20borkdudeIssue welcome#2023-09-0620:58skynetthanks, opened here https://github.com/clj-kondo/clj-kondo/issues/2179#2023-09-0718:23dpsuttonanyone ever see this error? > user=> (require ’[clj-kondo.hooks-api :as hooks]) > Syntax error compiling at (clj_kondo/impl/analysis/java.clj:61:6). > Unable to find static field: ASM9 in interface org.objectweb.asm.Opcodes#2023-09-0718:24borkdudewhat java version are you using? (not sure if it's relevant..)#2023-09-0718:24borkdudeperhaps one of your dependencies downgrades ASM#2023-09-0718:24dpsuttonit seems we have a conflict on ASM
❯ clj -Sdeps '{:deps {clj-kondo/clj-kondo {:mvn/version "2023.09.07"}}}'
Clojure 1.11.1
user=> (require '[clj-kondo.hooks-api :as hooks])
nil
user=>
#2023-09-0718:25dpsuttonsorry for the noise 🙂#2023-09-0718:43dpsuttonif anyone else finds this, it was eastwood on the classpath
jonase/eastwood 1.4.0
  . org.clojars.brenton/google-diff-match-patch 0.1
  . org.ow2.asm/asm-all 5.2
and that asm-all brings in a seriously old version
user=> (io/resource "org/objectweb/asm/Opcodes.class")
#object[java.net.URL
        "0x37e9d2e2"
        "jar:file:/Users/dan/.m2/repository/org/ow2/asm/asm-all/5.2/asm-all-5.2.jar!/org/objectweb/asm/Opcodes.class"]
versus the org.ow2.asm/asm 9.4 :superseded expected by clj-kondo
#2023-09-0718:44borkdudewhen using tools, it's usually best to separate their classpaths. deps.edn got this right with -T(ools) usage#2023-09-0718:45borkdudeunless you want to invoke them all from the same JVM of course#2023-09-0718:45dpsuttonagree. we have a dev alias which has some stuff that we’ve been pretty casual about. i guess the classpath finally shifted around and now it’s finding those bundled 5.2 versions instead of a 9.4 version#2023-09-0718:46dpsuttoni think eastwood needs to live on your regular classpath because it runs your tests and requires all of your code. but your point is still valid#2023-09-0718:47borkdudegood point about eastwood#2023-09-0721:26seancorfieldI run Eastwood as a standalone process via build.clj in HoneySQL https://github.com/seancorfield/honeysql/blob/develop/build.clj -- why do you have it on the dev classpath @U11BV7MTK?#2023-09-0721:28dpsuttonthat’s a great question. i think because dev became a grab bag of “handy” stuff. Although I’m not sure if there’s a dev related workflow for eastwood. we even have an alias for it for CI. I suspect it was considered “dev” tooling and perhaps someone might want it#2023-09-0721:28dpsuttoni need to build a tool to identify all classes on the classpath that are duplicated. because it’s wild that we have asm-all and asm with such different versions. and so the version of that class you get is completely undefined. i guess bumping some versions shifted which came first on the classpath#2023-09-0721:30seancorfieldThis is why I don't even really like nREPL/CIDER on my dev classpath 😉#2023-09-0721:30dpsuttonhasn’t been on mine for years now#2023-09-0721:30dpsuttoni thought you were exclusively nrepl these days#2023-09-0721:31seancorfieldYeah. Calva needs it. And CIDER for all things to work.#2023-09-0721:32seancorfieldWith remote processes, I only have nREPL, no CIDER, and only in a couple of internal-facing apps (they have "everything" so I don't need to connect to any other processes).#2023-09-0721:32dpsuttoncider-nrepl shades everything so it shouldn’t be an offender for that reason#2023-09-0721:35seancorfield
cider/cider-nrepl 0.37.0
  . nrepl/nrepl 1.0.0
  . mx.cider/logjam 0.1.1
So... not too bad... but it's still a lot of extra code 😐
#2023-09-0721:36dpsuttonoh yeah. a decent chunk of code. but the classes will be renamed. i’m not familiar with logjam. i haven’t followed development too much recently#2023-09-0721:39seancorfieldI don't follow nREPL/CIDER dev at all -- I mostly just pretend it doesn't exist and let Calva add the dependencies at jack-in or pull a "RELEASE" version from an alias 🙂#2023-09-1916:51vemvI hit this issue, but for another reason: mranderson was part of the Lein :plugins. > when using tools, it's usually best to separate their classpaths. deps.edn got this right with -T(ools) usage This. Normally I try for every tool to go under a separate Lein profile e.g.:
:clj-kondo {:plugins [[com.github.clj-kondo/lein-clj-kondo "2023.09.07"]]}
#2023-09-1320:11mauricio.szaboHi there! I'm using :discouraged-var for a specific project, but somehow if I add the :level :error it still detects as warning. I tried to change to :level :off just to be sure that it turns the whole warning off, and indeed it does... am I doing something wrong?#2023-09-1321:59borkdudeWill look tomorrow#2023-09-1410:03borkdudehttps://github.com/clj-kondo/clj-kondo/issues/2183#2023-09-1420:23mauricio.szaboGreat, thanks a lot! 🙂#2023-09-1321:42skynethey, not sure if there's a better tool or method here but: given a file test.edn
[:a :b]
[:c :d]
how can I "lint" this (with clj-kondo maybe) to warn that the [:c :d] part will be thrown away if say I do
=> (-> "test.edn" slurp clojure.edn/read-string)
[:a :b]
(based on a true story...)
#2023-09-1322:01borkdudeThe data by itself does not constitute an error, if you read this in a loop using a reader it will work #2023-09-1411:05gordonIs it possible to use hooks to tell clj-kondo that a namespace is used? For hysterical raisins, we have some ancient code with circular dependencies which are extremely complicated to unwind. I'd like to unwind as much as I can, but the way these circular dependencies were added currently defeats clj-kondo's analysis, which makes finding unused code with carve harder. Back in the mists of time a macro was added to our codebase that implements a lazy definition of a function in another namespace: (declare-fn other.namespace/function) This macro will create the namespace if necessary, and define a function which on first invocation requires the namespace if necessary, resolves the function's symbol in that namespace, and then invokes the real function. What I'm looking to do is to teach clj-kondo's analyser that the namespace passed to declare-fn should be considered as required My first attempt was to use a hook to rewrite (declare-fn other.namespace/function) into (require '[other.namespace :refer [function]), but that doesn't seem to impact namespace analysis. Is what I'm looking to do possible? Thanks again for the suite of super-useful tooling, I use carve and clj-kondo every day.#2023-09-1411:06borkdude"hysterical raisins" 🍇 great typo 😃#2023-09-1411:07borkdude
(declare-fn other.namespace/function)
does hooking this as requiring-resolve work?
#2023-09-1411:07gordonLet me check#2023-09-1411:09borkdudeI don't think it does, unfortunately#2023-09-1411:09borkdudebut what you can do... (this will take me a time to type)#2023-09-1411:14gordonConfirmed that requiring-resolve doesn't work#2023-09-1411:18borkdudeThere's no easy way to do this, but if you add the namespaces to {:linters {:unresolved-namespace {:exclude [...]}}} then clj-kondo will assume that those are loaded by you#2023-09-1411:19gordon👍 great, thanks for the help 🙂#2023-09-1411:19borkdudebut carve likely won't see that it's being used... this could be improved though#2023-09-1411:22gordonNo bother, I'm sure this is a very niche use-case, most folks don't go to these lengths to add circular dependencies to their codebases 🙂#2023-09-1411:25borkdudeyou can always add them to the ignore list of carve#2023-09-1411:26gordonThanks I'll give that a shot#2023-09-1413:33reefersleepI'm very curious; why was the circular dependence deemed necessary? (Maybe you don't know 😄 )#2023-09-1416:49gordonThe honest answer is "poorly structured code". It was allowed to last long enough that it's deeply entrenched.#2023-09-1416:51reefersleepIt happens. You're busy building, and don't realize that the foundation is being eroded.#2023-09-1416:52borkdudeI have some of this in clj-kondo. The analyzer.clj namespace is huge so I wanted to chop it into a few subparts, but those sub parts also need functions from analyzer.clj
#2023-09-1416:53borkdudeWhat I did is create a analyzer/common.clj namespace and put a bunch of atoms in there in which I set the functions which I then use from the sub-namespaces#2023-09-1416:53borkdudeit breaks clj-kondo/lsp references but at least it's not cyclic#2023-09-1421:03reefersleepHeh, that's funny that you're actively preventing your own tool from working on itself.#2023-09-1421:11borkdudewell, not actively. clojure-lsp didn't even exist when I did it like that ;)#2023-09-1421:54reefersleepAh 😅 well, doesn't it also prevent some analysis that clj-kondo could otherwise have done? Of function usage and such.#2023-09-1421:55borkdudeyes, but a man's gotta do what a man's gotta do when you want to prevent cyclic dependencies and still split things up#2023-09-1422:00reefersleepSure sure, whatever makes sense in a context. The notion just made me smile 😊 #2023-09-1422:02borkdudethese are those things: https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/analyzer/common.clj I still get arity warnings and I only use them from a limited number of places, so it's ok-ish#2023-09-1611:17reefersleepAlso, you're the boss, so that helps#2023-09-1415:33lilactownI can't seem to get clj-kondo to copy the config for helix into a new project.
;; shadow-cljs.edn
{:source-paths ["src"]
 :dependencies [[lilactown/helix "0.1.10"]
                [binaryage/devtools "1.0.7"]]}
output of copy config command:
$ clj-kondo --lint "$(shadow-cljs classpath)" --dependencies --parallel --copy-configs
shadow-cljs - config: /Users/lilactown/Code/helix-fundamentals/shadow-cljs.edn
No configs copied.
#2023-09-1415:34borkdudedo you have a .clj-kondo directory?#2023-09-1415:34lilactownno#2023-09-1415:34borkdudeyou have to create one yourself, this is clj-kondo's way of giving it permission to write to a local folder#2023-09-1415:34lilactownI see. is that documented somewhere?#2023-09-1415:35lilactownif it is, I must have missed it#2023-09-1415:35lilactown
$ mkdir .clj-kondo
$ clj-kondo --lint "$(shadow-cljs classpath)" --dependencies --parallel --copy-configs
shadow-cljs - config: /Users/lilactown/Code/helix-fundamentals/shadow-cljs.edn
Configs copied:
- .clj-kondo/lilactown/helix
🎉
#2023-09-1415:35borkdudehttps://github.com/clj-kondo/clj-kondo#project-setup#2023-09-1415:36lilactown> To detect lint errors across namespaces in your project, a cache is needed. To let clj-kondo know where to create one, make a .clj-kondo directory in the root of your project, meaning on the same level as your project.clj, deps.edn or build.boot. missed it in my skimming then 🙂#2023-09-1415:43borkdudeclj-kondo could make this clearer though in its error message; issue welcome#2023-09-1508:11Julian AlbaHello, can I set up clj-kondo to analyze .clj files as .cljc or even better change node language in hook? I have clojurescript macro that compiles forms to JS for <script> tag. It works well, except clj-kondo shows clojure (not script) warnings. I was able to write a hook for .cljc as suggested by @borkdude https://clojurians.slack.com/archives/CHY97NXE2/p1667912798502989, but I would like to keep file extensions as is.
(defmacro clojurescript [& forms]
  (emit
   (analyze
    (empty-env)
    (into forms `(do)))))

(clojurescript
  (js/console.log x))
#2023-09-1508:13borkdudeyou can't do this, just suppress certain errors in the clojurescript macro, with:
{:config-in-call {my.ns/clojurescript {:linters {:unresolved-namespace {:exclude [js]}}}}}
#2023-09-1509:35Julian AlbaMake sense, thanks. By the way, I ❤️ clj-kondo so much, thank you for it!#2023-09-2112:48Martynas MaciulevičiusHey. What is the best way to suppress linter error from a macro in a library that I don't control? This library is from 2012 but they added a commit recently. I could add a config.edn but is this the best way?#2023-09-2112:50Martynas MaciulevičiusThis is what the template macro does:#2023-09-2112:56Martynas MaciulevičiusThere is this issue but the library author closed it: https://github.com/brandonbloom/backtick/issues/8#2023-09-2113:04delaguardoI would add :lint-as {backtick/defquote clojure.core/def} to the .clj-kondo/config.edn#2023-09-2113:07Martynas MaciulevičiusThis worked. Thanks 💯#2023-09-2113:08delaguardothat wouldn't fix the problem with unresolved symbols but at least template macro will be known to kondo#2023-09-2113:09delaguardo#2023-09-2113:09Martynas MaciulevičiusThat fixes the underlying outside symbols not being "used" and I think that I can fix the unknown macro by adding one more rule. But the undefined symbols is actually already good.#2023-09-2113:13Martynas MaciulevičiusI did this and it fixed the underlying unknown symbols:
{:lint-as
 {backtick/defquote clojure.core/def}
 :linters {:unresolved-symbol {:exclude [(backtick/template)]}}}
But then the template macro itself is said to be undefined. So I added this to the code:
#_{:clj-kondo/ignore [:unresolved-var]}
I'm not sure how to fix it.
#2023-09-2113:16delaguardoone way - keep only :lint-as {backtick/defquote clojure.core/def} and then ignore unresolved symbols close to the usage of template:
(let [x 5 v [:a :b]]
  #_{:clj-kondo/ignore [:unresolved-symbol]}
  (b/template {:x ~x, s #{~@v "c" inc}}))
#2023-09-2113:19Martynas MaciulevičiusI also want to ignore the non-existent-var somehow. But I don't know how to write it. This doesn't work:
{:lint-as
 {backtick/defquote clojure.core/def}
 :linters {:unresolved-symbol {:exclude [(backtick/template)]}
           :unresolved-var {:exclude [(backtick/template)]}}} <------------------------- this
#2023-09-2113:20delaguardowhy you need to ignore unresolved-var?#2023-09-2113:21Martynas MaciulevičiusBecause backtick/template gives this:
Diagnostics:
1. Unresolved var: backtick/template [unresolved-var]
So I want to add #_{:clj-kondo/ignore [:unresolved-symbol]} line but add it globally into the config if anybody would want to use this macro. I want it only for the macro and not underlying form :thinking_face: So that I would be able to forget that it existed.
#2023-09-2113:22delaguardothat should be fixed by linting backtick/defquote as clojure.core/def at least it works in my playground#2023-09-2113:22Martynas MaciulevičiusI added your rule but it's not fixed :thinking_face:#2023-09-2113:24Martynas Maciulevičiusthis:
{:lint-as
 {backtick/defquote clojure.core/def}
 #_#_:linters {:unresolved-symbol {:exclude [(backtick/template)]}
               :unresolved-var {:exclude [(backtick/template)]}}}
Results in this:
#2023-09-2113:24delaguardohm... here is what I have: in .clj-kondo/config.edn {:lint-as {backtick/defquote clojure.core/def}} and in the source code:
(let [x 5 v [:a :b]]
  #_{:clj-kondo/ignore [:unresolved-symbol]}
  (b/template {:x ~x, s #{~@v "c" inc}}))
rerun your linter to force kondo diagnostics to see if it actually works
#2023-09-2113:26Martynas MaciulevičiusI restart my IDE and it reloads the config but it doesn't suppress the nonexistent ns var error. And importing [backtick :as b] doesn't help too as b/template gives the same error.#2023-09-2113:27Martynas MaciulevičiusI don't add #_{:clj-kondo/ignore [:unresolved-symbol]} into the source code. I want to make it work without it.#2023-09-2113:27Martynas MaciulevičiusIt works with it but I don't want to use it.#2023-09-2113:29delaguardoto disable unresolved-symbol globally for b/template:
{:lint-as {backtick/defquote clojure.core/def}
 :linters {:unresolved-symbol {:exclude [(backtick/template)]}}}
#2023-09-2113:30delaguardobtw, do you know your kondo version?#2023-09-2113:32Martynas MaciulevičiusThis covers everything:
{:lint-as
 {backtick/defquote clojure.core/def}
 :linters {:unresolved-symbol {:exclude [(backtick/template)]}
           :unresolved-var {:exclude [backtick/template]}}}
#2023-09-2113:33Martynas MaciulevičiusI upgraded my system yesterday.
clojure-lsp --version
clojure-lsp 2023.08.06-00.28.06
clj-kondo 2023.07.14-SNAPSHOT
#2023-09-2114:48borkdudeYou can lint as syntax quote using a hook, there is one in clerk#2023-09-2208:01raymcdermottA JS interop case that bit me yesterday was this line: (js/console "Something" js-obj-thing) and of course I meant js/console.log "Something" js-obj-thing but the output was to debug a third party library whose calling semantics were a bit obscured cos it's written in TS and I was getting all kinds of other errors that blinded me to that SNAFU ... totally floored when I realized that I had fixed the call to the library 30 mins ago but was still banging my head trying to understand this
TypeError: Function.prototype.apply was called on #<Object>, which is a object and not a function
    at bt (file:///home/ray/acme/repos/publish-rate-card/node_modules/nbb/lib/nbb_core.js:338:125)
    at file:///home/ray/acme/repos/publish-rate-card/node_modules/nbb/lib/nbb_core.js:597:410
    at R (file:///home/ray/acme/repos/publish-rate-card/node_modules/nbb/lib/nbb_core.js:309:469)
    at file:///home/ray/acme/repos/publish-rate-card/node_modules/nbb/lib/nbb_core.js:558:423
    at R (file:///home/ray/acme/repos/publish-rate-card/node_modules/nbb/lib/nbb_core.js:309:469)
    at file:///home/ray/acme/repos/publish-rate-card/node_modules/nbb/lib/nbb_core.js:559:305
    at R (file:///home/ray/acme/repos/publish-rate-card/node_modules/nbb/lib/nbb_core.js:309:469)
    at file:///home/ray/acme/repos/publish-rate-card/node_modules/nbb/lib/nbb_core.js:418:411
    at file:///home/ray/acme/repos/publish-rate-card/node_modules/nbb/lib/nbb_promesa.js:39:342
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
#2023-09-2218:26Jordan YeeThis makes me wonder if it would be useful to support a simple regex rule type (if there isn't already such a thing). For a static case like this, you would define a rule something like:
{:regex {:match "js/console "
              :message "Did you mean `js/console.log`?"}}
#2023-09-2219:30raymcdermottYes - would be 😎 #2023-09-2208:02raymcdermottHaving a warning that it was not js/console.log or js/console.error would have been nice 🙂#2023-09-2209:02raymcdermottoh, and the rule should be called consolation 😛 ... I'd be interested in making a PR if you want to give me a steer @borkdude#2023-09-2211:52borkdudeHey Ray, thanks for the ideas, but not sure how generalizable this is. There might be objects on js that are legit, defined by libraries as globals. How would clj-kondo know what's valid?#2023-09-2212:12raymcdermottYeah, I’m not sure how to make it general but I still think that having some known good vs unknown states could be useful. Somebody might have console globally but if it is in the function slot, it should be callable ie not an object or an object property #2023-09-2212:14raymcdermottI’m riffing here though… I’m sure you have a better grasp on what is feasible #2023-09-2216:55martinklepschHello — I'm using lambdaisland/glogi and sometimes it happens that I do something like (log/info :test) but since glogi expects map-entries this should be at least (log/info :test nil) — I tried adding a :lint-as entry pointing to clojure.core/hash-map but so far it doesn't seem like that is being picked up. Am I missing anything here?#2023-09-2218:23borkdudeI’m at Strange loop but I’ll set a reminder for next week #2023-09-2218:46martinklepschthank you! enjoy strange loop 🙂#2023-09-2613:08borkdudeI guess lint-as doesn't really treat type checking the same way, maybe for good reasons#2023-09-2617:12martinklepschah but isn't this more of an arity-check in a way?#2023-09-2617:27borkdudethe hash-map function is varargs#2023-09-2617:27borkdudebut yes, in a way it is#2023-09-2617:28borkdudebut this is going via the type checking mechanism#2023-09-2617:29borkdudeit's expecting an even number of things which it is then going to type check#2023-09-2617:30borkdudeI don't think lint-as affects arity checking, it's mostly for getting rid of unknown macro syntax things#2023-09-2617:31borkdudeyou could set this type for glogi/log manually:
'hash-map {:arities {:varargs {:args [{:op :rest :spec [:any :any]}]
                                  :ret :map}}}
#2023-09-2617:34borkdude
{:linters {:type-mismatch {:namespaces {lint-as {dude {:arities {:varargs {:args [{:op :rest :spec [:any :any]}]
                                                                           :ret :map}}}}}}}
#2023-09-2617:43martinklepschThanks, that's doing what I was looking for 🙂#2023-09-2617:43martinklepsch🙌#2023-09-2617:46borkdudenice :)#2023-09-2617:46borkdude🙌#2023-09-2405:58ingesolI’m seeing a warning on some code that mutates in place and returns the value after. I can just ignore it, just wanted to ask if this is expected and wanted.
clj-kondo --lint - <<< "(let [res (transient [])] (conj! res 1) res)"
<stdin>:1:27: warning: Unused value
linting took 22ms, errors: 0, warnings: 1
#2023-09-2405:59borkdudeyes, this is a very desirable warning since transient operation results should be used, if not, weird things can happen since a transient op can return a different object than you had originally#2023-09-2406:00borkdudeyou can read more in this reddit post + comments: https://www.reddit.com/r/Clojure/comments/muqetg/transient_set_loses_data/#2023-09-2406:10ingesolWow, thanks that’s very interesting 🙂#2023-09-2510:32phillThis is described, BTW, at https://clojure.org/reference/transients#2023-09-2510:33borkdudeThanks for providing that link#2023-09-2618:05André CamargoHello my friends! Just a sanity check. Are these warnings expected? 🧵#2023-09-2618:07André CamargoI didn't expect those warnings...#2023-09-2618:28dpsuttonkeep a mental model that clj-kondo will lint the clj visible parts and then the cljs visible parts#2023-09-2618:29dpsuttonclojure.string is required in cljs but never used. and therefore a warning#2023-09-2618:30dpsuttony is defed but never used in cljs code pathways#2023-09-2618:30dpsuttongen-func and count are unused bindings in pin-sample cljs code pathways, etc#2023-09-2618:32André Camargooh, I see now... :thinking_face:#2023-09-2618:40André CamargoIt makes sense @U11BV7MTK, thank you so much!#2023-10-0415:07Matthew TwomeyRather than using bash scripts, I’ve been using babashka scripts these days. I love this. I’ve noticed that kondo won’t kick on fully and provide completions, unless I have a bb.edn file along side my .bb script. That file just needs to contain an empty map and then kondo works fine (I think I read this requirement somewhere). My question is: Is there a way to force kondo to engaged from within emacs so that I don’t need to have that empty bb.edn file?#2023-10-0415:09borkdudecompletions are provided by #CPABC1H61 (which in turn uses clj-kondo) and lsp is always project-based#2023-10-0415:10borkdudewhich means that you will need a deps.edn or bb.edn in order for lsp to do anything#2023-10-0415:14Matthew TwomeyOk.. I don’t love this, but I hear you. So if it were possible to do anything in this regard (so that I don’t need an accompanying empty bb.edn), that would be an lsp question?#2023-10-0415:14borkdudeI don't love it either, and yes, it's an lsp question :)#2023-10-0415:16Matthew TwomeyOk - I’ll add my voice to that discussion as well.#2023-10-0503:41hifumi123I dont use clojure-lsp, but I have ran into a similar annoying situation with Node Babashka, until I learned about cider-jack-in-universal . This allows me to spawn nbb from anywhere, even without an nbb.edn file, and I get a REPL + autocomplete for ClojureScript and Node.js code#2023-10-0503:42hifumi123cider-jack-in-universal supports four different types of “projects”, without needing you to make a project file yourself: lein, deps.edn, nbb, and babashka I almost exclusively use it with nbb#2023-10-0504:27Ngoc Khuatcould anyone help me understand why {:a 1} creates an array-map instead of a hash-map? IMO hash-map has O(1) lookup time which is pretty nice. On the other hand, array-map has the benefit of maintaining insertion order, but I don’t think we really need that property.#2023-10-0504:43seancorfieldThis doesn't seem to be a clj-kondo question but I'll answer it here anyway: small hash maps (up to 8 entries) use an array map, then it switches to a hash map. This is an implementation detail and you shouldn't rely on it. Array map has a much simpler implementation than a regular hash map so it's better for overall performance/memory usage for small maps, as I understand it.#2023-10-0505:30Ngoc Khuatah nice! that actually makes sense! Thank you Sean. And sorry I meant to ask in #C03S1KBA2#2023-10-0507:05lispyclouds@U023C0QKU4W purely as a fun exercise you can try measuring the perf of looking for something (membership check) in a small fixed sized array vs a map, say upto 10-15 elements. the results might surprise you 😉 the C times O(n) vs C times O(1) starts to matter when n is small#2023-10-0514:44seancorfieldI should also have mentioned that hash maps use a chunked hash trie, with a chunk size of 32, which is really efficient for large maps but still involves a number of sequential comparisons.#2023-10-0600:22hifumi123lookups in a hash map are not O(1), they are average O(1), which can be quite different from O(1) worst case#2023-10-0600:23hifumi123for small hash maps, it is actually faster to use a flat array that fits in a CPU cache line, you can benchmark this yourself in any language, not just Clojure#2023-10-0600:25hifumi123at least my theory as to why array-map stops at 8 kv pairs is due to the fact that 16 pointers in a modern JVM (assuming pointer compression) is exactly the size of a cache line in modern x86 and ARM processors (64 bytes)#2023-10-0911:37borkdudeHere is a proposal for an extension to the :consistent-alias linter which checks consistency of aliases between multiple files: https://github.com/clj-kondo/clj-kondo/issues/2195 I've previously not implemented this because it would not work in an editor, but for command line usage it's probably still useful, right?#2023-10-0915:57seancorfieldI can see this being useful via clojure-lsp if it could figure out the most common alias used for a given ns and then flag all the other aliases as not matching that. I would not use this, however, because we have a convention of always using sut as the alias for the primary ns being tested in our test nses, so it would always flag those as inconsistent. We tend to use the alias linter almost solely for 3rd party nses.#2023-10-0915:59phillsut ≟ stuff undergoing testing#2023-10-0916:00borkdudewell, we could build a configurable exclusion for sut etc of course#2023-10-0916:02borkdudeclojure-lsp already has the data it needs to implement this feature. clj-kondo could do it too but then you'd just get the feature when linting a directory, not via the editor (unless we keep more stuff in the on disk cache, which is kinda complicated)#2023-10-0916:02borkdudecc @UKFSJSM38#2023-10-0916:07ericdalloI do think this is quite useful, but IMO would be nice to have built-in clj-kondo similar to unresolved-var linter which has context about other ns#2023-10-0916:10seancorfieldIf you have 100 uses of a ns and only one is inconsistent, the order you lint the code matters... If you see the inconsistent use first, the other 99 will be flagged; if you see it elsewhere, only that 1 use would be flagged:grin:#2023-10-0916:11ericdalloAFAIK clj-kondo does that for unresolved-var lint which reports when you have a unknown function from an alias#2023-10-0916:12borkdudesure, I'm willing to think about it but then we get at the "complicated caching" bit, since clj-kondo needs to know about all aliases used in the project for a certain namespace. the process would be like this, when in an editor:
(ns foo (:require [clojure.string :as str]))
store {clojure.string {str {foo}} or so (not sure which layout is most handy and then lint the next file in an editor:
(ns bar (:require [clojure.string :as string]))
Add to index
{clojure.string {str #{foo} string #{bar}})
Now we find that there are multiple aliases, so we can show that there is another namespace with a different alias. But if you remove (:require [clojure.string ]) from foo how do we update the index? There is not a single layout which is optimal for querying probably. When you have a server process like with clojure-lsp, it becomes a little easier
#2023-10-0916:15ericdalloGot it, how we update the cache for the unresolved-var case? indeed doing in clojure-lsp should be easier#2023-10-0916:16borkdudeunresolved-var and invalid-arity, etc etc are all just part of layout by namespace#2023-10-0916:17borkdude
.clj-kondo-cache/v1/foo/bar/baz.transit.edn
(there are some indirections in there per clojure dialect, but this is the main idea)
#2023-10-0916:22ericdalloI see, I think I or @U04CAPVN1HS can take a look how hard would be to implement as a new custom linter in clojure-lsp#2023-10-0916:41borkdudeI think the only difficult thing about the on disk cache is: how to efficiently detect removals, e.g. when you change or remove an alias, how would you efficiently update the on disk cache#2023-10-0916:41borkdudebut perhaps this problem is actually similar with clojure-lsp, but just in memory#2023-10-0918:44ericdalloyep, we already do the same for unused-public-vars, so we have a ns dependency graph which helps both in performance and find that#2023-10-0918:48borkdudenice#2023-10-1015:00Thayanne SousaHello! Is there a field to specify a docs url for the linter/hook to show it along with lint message? Or the only way to do it is to add the link in the :message field?#2023-10-1015:39borkdudeThere's no special field for it#2023-10-1015:51Thayanne SousaWdyt about something adding it as an optional field? Linters like https://eslint.org/docs/latest/extend/custom-rules#rule-structure have support for this The message could be a hyperlink to it, or at the ending of the finding we can add a hyperlink “Docs”#2023-10-1016:10borkdude@U04CT70C8CU Interesting idea. Where would this link be displayed, or just in the data output?#2023-10-1016:46Thayanne SousaI think in the data output, along with the message#2023-10-1017:26borkdudeYou mean in a hook right?#2023-10-1017:26borkdudeWhat happens if you simply feed a :doc key to reg-finding!?#2023-10-1118:38Christian JohansenI have a ClojureScript library that defines a macro in src/portfolio/react.clj , and some cljs functions in src/portfolio/react.cljs. People typically use it like so: (require [portfolio.react :refer-macros [defscene]]) (code is here btw: https://github.com/cjohansen/portfolio/blob/main/src/portfolio/react.clj / https://github.com/cjohansen/portfolio/blob/main/src/portfolio/react.cljs). The macro has optional parts, but can look like this:
(d/defcomponent SideEffecty
  :key value
  ,,,
  [data]
  [:h1])
Is there any way I can provide some config, metadata or other in the library that will help clj-kondo understand this macro in projects that depend on the library? Ideally it'd understand both that SideEffecty is being defined, and that data is a binding.
#2023-10-1119:50borkdudeYep. On phone right now but take a look at lint-as + catch-all in the config.md docs #2023-10-1119:50borkdudeThe other option for recognizing the binding requires a hook, see hooks.md#2023-10-1121:19Christian JohansenCool, thanks. Can I ship these with the library somehow? If it's covered in the docs I'll find it 😅 #2023-10-1121:20borkdudeYes :) https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration#2023-10-1121:22borkdudeHere's a long list of examples: https://github.com/clj-kondo/clj-kondo/discussions/1528#2023-10-1220:34Christian JohansenVery cool 🙏 Thanks again, and sorry for not responding - I overstretched a little 😅#2023-10-1315:51Sam RitchieYou can also remove the refer-macros requirement -#2023-10-1315:52Sam RitchieOn the cljs side add a form like this to the namespace declaration https://github.com/mentat-collective/emmy/blob/e16b5692b04972f0bc9ea6d07f7ead41edccc066/src/emmy/util/def.cljc#L6#2023-10-1315:52Sam RitchieAnd then your users can use :refer or just the alias from require without treating the macro in a special way #2023-10-1317:27Christian JohansenWow, interesting. Am I understanding this right, that the cljs-part of the cljc-file will effectively be merged with the same-named cljs file?#2023-10-1317:28Sam Ritchie@U9MKYDN4Q sorry my example here is slightly confusing — in this case I am using a single cljc file instead of separate clj and cljs files#2023-10-1317:28Sam Ritchieso for your example you would have to add that form to your cljs file only#2023-10-1317:38Christian JohansenAha, right#2023-10-1317:38Christian JohansenThanks#2023-10-1716:38jcfIs it possible to teach clj-kondo to ignore the more dynamic parts of libpython-clj? I’m being told off for using (py/py. ndarray tolist) even though I’ve configured clj-kondo to exclude that var. :thinking_face: I’ve got a reproducible example up on GitHub here: https://github.com/jcf/kondo-libpython#2023-10-1716:39jcfThere’s also this really weird issue with having to exclude py/py rather than py/py. — I guess because a dot means something else where in Clojure. https://github.com/jcf/kondo-libpython/blob/dbaf8429cdedd8d8f0a529fe4eecc0ec7e012110/.clj-kondo/config.edn#L16#2023-10-1717:48borkdudeI'll have a look#2023-10-1718:32borkdudeit's the constructor call that makes this not work#2023-10-1718:35borkdudeThe issue is that this is expanded into
(new py/py ndarray toList)
in clj-kondo
#2023-10-1718:36borkdudebut since there is a slash in the name, this should not be interpreted as a class, but as a var. still the name is unfortunate I'd say#2023-10-1718:43borkdudeSee discussion in https://clojurians.slack.com/archives/C03S1KBA2/p1697567906824569 I think my suggestion would be to rename the var in libpython-clj to avoid conflicts with new and deprecate the old vars#2023-10-1718:52borkdudetl;dr: The reader page says “Symbols beginning or ending with '.' are reserved by Clojure.”#2023-10-1718:54borkdudemade an issue for that: https://github.com/clj-kondo/clj-kondo/issues/2199 hopefully libpython-clj will adapt#2023-10-1719:00jcfThank you, @U04V15CAJ! :man-bowing: #2023-10-1719:03borkdude@U06FTAZV3 for now what you could do is make your own wrapper macro which defers to py. and then add that to clj-kondo's config.edn#2023-10-1917:53Stefan@borkdude Are you planning for a new clj-kondo release soon? The fix in https://github.com/clj-kondo/clj-kondo/issues/2190 would allow me to start the :unused-alias linter. 🙂#2023-10-1918:03borkdudeYes, I'm working towards a release#2023-10-1918:03StefanAwesome. Not trying to hurry you! Just curious 🙂#2023-10-1918:03borkdudeyes, soon#2023-10-2112:40peterhI want to create an empty array that holds keywords, using (make-array clojure.lang.Keyword 64) . This works fine without any imports, but clj-kondo marks this with an error "Unresolved symbol: clojure". I tried explicitly importing it, using (:import [clojure.lang Keyword]), but the error persists. Is there a simple workaround or do I have to configure clj-kondo to ignore this case somehow?#2023-10-2113:08borkdudeIs this in a .cljc namespace?#2023-10-2113:12peterhOh well, I forgot… yes it is. A reader conditional made the error go away. 😅#2023-10-2419:25Alexander KouznetsovIs it correct that lint-as can’t be used to lint several macros using a single custom hook? The documentation for lint-as uses a phrase “built-in macro” which seems to suggest that custom hooks are excluded.#2023-10-2419:29Alexander KouznetsovIs there a way to collect data about how many warnings are related to each macro in the code that clj-kondo doesn’t understand? To the best of my knowledge, most macros confuse clj-kondo but the linting report only contains specific linting issues which aren’t linked to the root problem - an unrecognized macro. Is it possible to link an error or a warning to a specific unrecognized macro (and potentially separate true linting errors and false ones that require unrecognized macros fixes)?#2023-10-2501:58Alexander KouznetsovDo you mean that with analysis enabled, it will include the macro name/reference as part of the analysis or that given the data available in the analysis and the source code, it is possible to find the macros?#2023-10-2505:54borkdudeYou don’t need the source code#2023-10-2709:55socksySo we just had a fun production bug that looked like this:
(let [way-to-do-thing (if feature-flag-for-dangerous-thing-enabled?
                          :dangerous-way
                          :safe-way)] 
   ,,,); do stuff
The problem? feature-flag-for-dangerous-thing-enabled? was actually a function, and the programmer (and all the code reviewers, me included!) didn't realize that it was a function and not a boolean. Vars are truthy, so we ended up always setting way-to-do-thing to :dangerous-way, which was not ideal. I'm wondering — is there a foolproof way to write a linter that would have been able to catch this in a way that wouldn't make legitimate uses also fail? It'd be great if we'd caught this in CI in advance (we run kondo religiously!)
#2023-10-2709:57borkdude?#2023-10-2710:00socksysorry! Forgot that slack doesn't save "shift+enter" settings in code blocks between different slack workspaces and accidentally sent instead of started a new line 🙃#2023-10-2710:03borkdude@U066F8MGF I don't think you can do this using the existing linters, but you can inspect the analysis to search for usages of that var such that it isn't used in a literal function call#2023-10-2710:04borkdudebut this will also include stuff like (apply feature-flag-for-dangerous-thing-enabled? ...)#2023-10-2710:09borkdudeone thing that would allow you do catch this in the clojure application is to turn this feature function into a macro, such that (if feature-macro ...) will throw with can't take the value of a macro#2023-10-2710:14borkdude
(defn dont-use-this-directly []
  true)

(defmacro dangerous-feature-enabled? []
  `(dont-use-this-directly))

(if dangerous-feature-enabled? ...) ;; throws
#2023-10-2710:18socksywell this feature flag function was more of a one off for this namespace, but it strikes me that there's a more general rule — whenever you pass a var with a ? at the end to an if, and the var evaluates to a function instead of a boolean, then this is pretty much always a mistake, right?#2023-10-2710:19borkdudeno always, e.g.:
(def windows? (str/includes? (System/getProperty "os.name") ...))
#2023-10-2710:19borkdudebut if it's a function, yes, it's probably a mistake#2023-10-2710:20borkdudeso maybe a new linter: :function-as-condition would make sense#2023-10-2710:20borkdudeany function, including those without a question mark I'd say#2023-10-2710:21socksyyeah, we thought it was a bool var like that, hence getting past code review 😅#2023-10-2710:21borkdudeseems good to me, can you write this up in a github issue?#2023-10-2710:22socksyI will! thanks#2023-10-2710:40imreI kinda liked the java/c# restriction of only allowing boolean conditions... Make these explicit#2023-10-2710:41imre(true? fn-to-check-dangerous-feature-enabled?)#2023-10-2713:33socksyMade an issue here: https://github.com/clj-kondo/clj-kondo/issues/2207#2023-10-2713:33borkdudethank you!#2023-10-2713:34borkdudeI guess we could even make this a linter like :always-true or something#2023-10-2714:16borkdude
$ clj -M:clj-kondo/dev --lint - <<< '(if inc 1 2)'
<stdin>:1:5: warning: Condition always true
#2023-10-2714:55socksynice! From my testing:
> clj -M:clj-kondo/dev --lint - <<< '(def foo true) (defn bar [] true) (if foo 1 2)'

linting took 39ms, errors: 0, warnings: 0

> clj -M:clj-kondo/dev --lint - <<< '(def foo true) (defn bar [] true) (if bar 1 2)'

<stdin>:1:39: warning: Condition always true
linting took 39ms, errors: 0, warnings: 1

> clj -M:clj-kondo/dev --lint - <<< '(def foo :true) (defn bar [] true) (if foo 1 2)'

linting took 43ms, errors: 0, warnings: 0
this is what you're aiming for, right?
#2023-10-2714:56borkdude
Condition always true
Keyword: :condition-always-true.

Description: warn on a condition that evaluates to an always truthy constant, like when passing a function instead of calling it

Default level: :warning.

Example trigger: (if odd? :odd :even).

Example message: Condition always true.
#2023-10-2714:56borkdudeYeah, this is intentional since often you toggle such a variable for development#2023-10-2714:56socksythanks!#2023-10-2714:57borkdudeI'll add that to the description#2023-10-2714:57borkdudeor maybe another name for the linter will make that more obvious?#2023-10-2715:01socksy:condition-always-true-unintentionally?#2023-10-2715:02socksyalthough i suppose all of the linters could be suffixed with -unintentionally#2023-10-2715:07lassemaatta”Tautological condition” :)#2023-10-2715:12lassemaattaJust earlier today I was reviewing code with a similarish (if (filter pred coll) .. ..) construction, which I think is also always true. #2023-10-2715:16borkdudehmm yeah#2023-10-2715:17borkdudeI guess you could get a false positive with:
(def x false) ;; or true, or a function
(if x (if (fn? x) (x ...) x) ..)
#2023-10-2715:19lassemaattaAlso, perhaps the naming (and functionality) of this particular linter feature should not refer to just ”true”; a permanently falsy statement is also a bad.#2023-10-2715:26borkdudethis is true but a permanently true value is often unintentional whereas a permanently false value is almost never unintentional?#2023-10-2715:26borkdudee.g. (def x false) is often just a development switch#2023-10-2715:30lassemaattaah yes. I was thinking more of (when-not something ..), but I guess it makes sense to report that something as "condition-always-true"#2023-10-2715:35borkdudeI think I'll disable the linter in the coming release, so it can be tested a little bit more#2023-10-2715:48socksyjust ran it against Pitch's frontend and backend and no false positives; reintroduced the broken conditional and it caught it. (Also tried to run it against the entire monorepo and it ran out of heap space)#2023-10-2710:40robert-stuttafordother than carve, is there any way to quickly list namespaces in a source folder that are never required? so, unused-namespaces but from the target's perspective#2023-10-2710:43borkdude"from the target's perspective"?#2023-10-2710:44borkdudeyou can do it manually based on the clj-kondo analysis data but then you would be doing something similar to carve I guess#2023-10-2710:45borkdudeA simplified example can be seen here: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#unused-vars but this is based on vars, the code for namespaces would be very similar#2023-10-2710:50robert-stuttafordthank you!#2023-10-2714:56borkdude
Condition always true
Keyword: :condition-always-true.

Description: warn on a condition that evaluates to an always truthy constant, like when passing a function instead of calling it

Default level: :warning.

Example trigger: (if odd? :odd :even).

Example message: Condition always true.
#2023-10-2715:33borkdudeThe above linter is likely not to give any false positives, but please scan your code base using the master version in case I overlooked something:
clj -Sdeps '{:deps {clj-kondo/clj-kondo {:git/url "" :git/sha "6ed9cf6df2f036231b0e89c9c17fa21139afdf6e"}}}' -M -m clj-kondo.main --lint src
#2023-10-2716:11Noah Bogart
$ clj -Sdeps '{:deps {clj-kondo/clj-kondo {:git/url "" :git/sha "6ed9cf6df2f036231b0e89c9c17fa21139afdf6e"}}}' -M -m clj-kondo.main --lint dev src test --parallel
linting took 22811ms, errors: 0, warnings: 0
on our 200k line codebase
#2023-10-2717:13seancorfieldIt didn't trigger on our 140k line codebase (which has thousands of other warnings).#2023-10-3016:31dharriganYou know what might be handy (does it exist already?) - a go-to list of lint-as settings for libraries, for example, through trial-and-error, I managed to figure out that compojure.api.sweet/defroutes can be linted as clojure.core/def. It would be nice to be able to go to a webpage and for it to say "if you're using such and such a library and function, here is what you can lint it as..."#2023-10-3016:32borkdudeThere is even a better option: include the lint-as config with the library#2023-10-3016:34dharriganThat is indeed better, but requires co-operation with the library author - and for it to be released and so on. On the other hand, having a page where a reference can be found (and removed, once the library has been clj-kondofied) is a stop-gap easy win.#2023-10-3016:34dharriganAnd some libraries are deprecated and wont' be maintained anymore#2023-10-3016:34dharrigani.e., compojure sweet#2023-10-3016:34dharriganyet they are still used in codebases.#2023-10-3016:37borkdudethere's also a contrib project here that doesn't require coordination with authors: https://github.com/babashka/sci.configs#2023-10-3016:38borkdudesorry, wrong link: https://github.com/clj-kondo/configs#2023-10-3016:39dharrigan👍#2023-10-3016:45borkdudebut adding a wiki page could also work, it's better to have some tests around it though since these things tend to get stale#2023-10-3100:33emccueWould it be possible to make a lint rule which raises a warning if you require a namespace which is not from a library in your direct dependencies list#2023-10-3100:34emccue(bonus points if there is a way to include class imports in that)#2023-10-3100:35emccueI understand that it would be a bad idea in general - warning on everyone who has ring via ring/ring is a bit much - but i'm thinking of it with respect to things like clojure.tools.logging where even if you like something like pedestal.log its hard to prevent the other require from being suggested and just messing it up#2023-10-3100:54seancorfieldHow would you determine the namespaces on your dependencies list?#2023-10-3101:21emccueI guess you would need to know what files came from what dependency + your list of "top" dependencies#2023-10-3101:22emccuewhich is information I wouldn't be surprised if its lost#2023-10-3101:27dpsuttoni really like this idea though#2023-10-3101:31seancorfieldI guess you'd have to parse through JAR files and look for Clojure/Script source files... plus handle the AOT-compiled Clojure core libs to deduce namespaces from class names...#2023-10-3101:32Noah BogartThis feels like a #lsp lint given that clj-kondo tries to stay single-file#2023-10-3101:33Noah BogartLike how it adds the “unused public var” lint#2023-10-3101:33seancorfield(I can definitely see the potential benefits, to prevent you accidentally depending on something (via require) that happens to come in transitively now but might not later on)#2023-10-3108:45borkdudeIt's an interesting idea, but a few adjustments: clj-kondo isn't "single file", it does keep track of var information from all the files that it has seen, such that it can deliver arity and type errors, but: clj-kondo doesn't really do anything to decide what is your "project". you just throw code at it and it keeps information about it around in .clj-kondo/.cache. clojure-lsp will automatically read your deps.edn etc, I guess it could figure out which namespace came from which jar file and then backtrack this to deps.edn, etc. so yeah, the more logical place for this would probably be clojure-lsp. There is some added complexity to track which deps are in scope concerning aliases and classpath commands, etc. If you have a custom classpath command you can't easily know which deps were directly declared related to that#2023-11-0122:14dharriganI have a monorepo that I'm running some pre-commit hooks on, one of which is running clj-kondo against two clojure sub directories. There is a dev.clj in each sub directory and in each dev.clj there is a (defn go...). I'm getting a warning back from clj-kondo about a redefined var (since it's picking up two dev.clj and finding two (defn go...) in them, even 'tho these are separate standalone projects (admittingly, within a monorepo). I was hoping in the config I could do something like {:linters {:redefined-var {:exclude [dev]}}}, but I don't seem to see that as an option. Could this be considered as an enhancement to redefined-var config?#2023-11-0122:15seancorfieldCould you add an annotation to both of those functions to ignore that linter?#2023-11-0122:15borkdudeclj-kondo isn't designed to lint mono-repos in one go, you should just lint them separately I think#2023-11-0122:15dharriganI could yes, although I was hoping to set it in the config.edn file#2023-11-0122:15dharriganI know it would be ideal to lint them separately, but I have to work with the tooling and what it supports#2023-11-0122:16borkdudemaybe this works:
{:config-in-ns {dev {:linters {:redefined-var {:level :off}}}}}
#2023-11-0122:17dharriganInteresting, letmetrythat.#2023-11-0122:18dharriganbingo bango, that works superbly 🙂#2023-11-0122:19dharriganta 🙂#2023-11-0314:25Noah Bogartis there a neat way to get a summary of the kinds of errors/warnings in a project? so instead of each individual error, you get :unused-local-var - 50 warnings, :syntax-error - 10 errors etc#2023-11-0314:26borkdudeyou can programmatically create this by using clj-kondo as a JVM or bb library#2023-11-0314:26Noah Bogartare there examples in the repo of programmatically working on the results?#2023-11-0314:27borkdudeno but it's very straightforward, just check the :findings thing from the returned map#2023-11-0314:28Noah Bogartexcellent, thank you#2023-11-0314:28borkdudemost of the examples are around the analysis: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#2023-11-0618:23Alexander KouznetsovI have a codebase with ~2500 namespaces and ~400 custom macros and running clj-kondo for it currently generates ~700 errors and ~400 warnings. My goals it make clj-kondo stop producing any false positives for this codebase and I estimate that I might need to create hooks or lint-as rules for each of these macros. I’m wondering if there are any good shortcuts or supporting libraries or tools that make creating these hooks or lint-as rules easier? One random idea that I have is that hook generation code might often be created with something similar to syntax quoting - which helps generates hooks that simply rewrite the existing code into something that clj-kondo can understand. I’m wondering if somebody had a similar idea. In my vision a defmacro definition may include such a thing in its attrmap to introduce a replacement code for a hook. Something like this: (defmacro x {:clj-kondo/rewrite '(let [a {} b c] body)} [a b c & body] …) . Thoughts?#2023-11-0620:22borkdudeHey @UHS6PHL31 - it's an interesting idea, but right now you can almost achieve the same with
{:hooks {:macroexpand ...}}
The inline notation will imo lead to confusions, e.g. people will try to write things that refer to code outside of the form using syntax-quote perhaps.
#2023-11-1402:53Alexander KouznetsovThank you very much for your reply. This is quite interesting. I overlooked this initially. I’ve read the description in https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macroexpand and I’m puzzled by a few things: 1. It might be a bit confusing to have the same-named macro in the same-named namespace with potentially the same content only distinguishable by a path. Why does it need to be exactly the same (namespace and macro naming)? 2. The doc claims that locations info will be lost in some cases. Where can I find more detailed info about such cases and potential explanations about why the locations will be lost (or more importantly, how to use it so that no locations will be lost?) 3. How complex can be a macro in configuration, can it use syntax quotes, etc? What would determine whether a macro can be used as is for its config macroexpand macro? Maybe such macros can be configured to macroexpand automatically or by flagging them with some attr-map value? I guess I will have to try to see how #2 and #3 work. #1 seems to prevent macros from being reused - for example I have a number of macros defined in different namespaces that each can be potentially configured with the same macroexpand macro. Would it be possible to share a single implementation in such case?#2023-11-1405:03borkdudeYes, just point multiple times to the same macro in the config#2023-11-0700:50mikerodI ran into a unresolved-symbol kondo linting issue with cljs having a ns :require of the form [jszip :as JSZip] where jszip is a node dep. I had a line where I called it as a constructor (JSZip.) and that failed linting, via Error: Unresolved symbol: JSZip For now, I just suppress the warning. I think some kondo upgrade within the last several months is where this started to fail since I was upgrading this project today after like 6 months or so.#2023-11-0707:46borkdudeUse a string name for Js deps#2023-11-0707:47borkdudeThis isn’t related to clj-kondo upgrade, it’s been like this for a long time #2023-11-0715:12mikerodOh. Thanks. I should have already knew this. I do that all the time. Then I forgot. 😵 #2023-11-0816:43jpmonettashi eveybody! I'm working on a project which is full of macros so seeing lots of errors when running clj-kondo. I'm currently trying to ignore them with :
:config-in-call {app/the-macro {:linters {:unresolved-symbol {:level :off}}}
                ...}
etc. So a couple of questions : Is there a way of muting all linters for a specific macro? And is there a way of logging the linter error/warning keyword next to each error so I can know what to mute?
#2023-11-0816:47borkdudeyes: :config-in-call {app/the-macro {:ignore true}}#2023-11-0816:49jpmonettasthank!!!#2023-11-0816:49Noah Bogarti can help you write a hook if you would like that instead#2023-11-0816:50jpmonettasthanks @UEENNMX0T, I think for now ignoring them will be enough, but in the future I should probably do that#2023-11-0816:50Noah Bogarthas anyone explored auto-generating hooks from macro definitions? i wonder if it would be possible for "simple" macros to convert the syntax-quoted output into the relevant api/X-node forms#2023-11-0817:12borkdudeYou don’t even need to use the node stuff if you use the macroexpand hooks #2023-11-0817:16Noah Bogartright, but that requires duplicating the macro in the hook. i'm wondering if it would be possible to analyze the input and create a similar macroexpand hook without duplication#2023-11-0817:36borkdudewell, try it ;)#2023-11-0817:36borkdudeI think there's a number of caveats though which is why I haven't done it myself#2023-11-0817:37Noah Bogartyeah no doubt i'll run headfirst into them, but it's fun to try#2023-11-0822:18Ingy döt Nethttps://clojurians.slack.com/archives/CPABC1H61/p1699481214925639 is a thread where kondo told me a fib#2023-11-1119:30borkdude@ericdallo What problem occurred when you use underscores in namespace names? We should mention that in the documentation, else people won't know why this linter is going to warn https://github.com/clj-kondo/clj-kondo/issues/1753#2023-11-1120:58Alex Miller (Clojure team)I don’t think that actually is a problem, just an idiom#2023-11-1121:01ericdalloI should probably added more details and a repro, but it was an error indeed, I just can't recall :/#2023-11-1121:14ericdalloFound it on nubank's slack: the problem was that our clojure->dart custom lib expects ns with dashes and not underlines, so more like a convention indeed, not a real compilation or something problem. Even so, I do think this should be a warn linter, we can argue if should be enabled by default, but I think it's a common convention in clojure projects use dashes and not underlines for ns name#2023-11-1121:15borkdudeok agreed, just a convention#2023-11-1121:19borkdudemerged#2023-11-1409:15ingesolHi! Would it make sense to have a linter to warn about direct calls to the host environment, like js/window , java.lang.String ? It would be useful for codebases that need to be cross compatible (Node, JVM, browser)#2023-11-1409:38borkdudeis this just an idea or something you're experiencing as a problem? In my experience when writing a .cljc file you usually get sufficient warnings if you're trying to do a JVM thing in an un-reader-conditionalized part of the code#2023-11-1415:07ingesolThanks for the shift in perspective! It’s more of an idea I think. We have a huge CLJS-based app, and would like to test and run parts of it on nodejs. Converting everything to CLJC is probably not happening, but would be the sensible thing to do if we wanted it cross platform#2023-11-1413:59tragiclifestoriesHi! I'm wondering if somebody can help me with implementing an :analyze-call hook - basically I want it to take the second and after arguments of the macro invocation and produce (-> nil arg2 arg3) etc. 🧵#2023-11-1414:00tragiclifestoriesWhat I have is:
(ns hooks.spec-generate
  (:require [clj-kondo.hooks-api :as api]))

(defn generate-> [{:keys [node]}]
  (let [[_ & body] (rest (:children node))
        new-node (api/list-node
                  (list*
                   (api/token-node '->)
                   nil
                   (if body
                     body
                     (api/list-node
                      (api/keyword-node :default)))))]
    {:node new-node}))
#2023-11-1414:01tragiclifestoriesBut when the call site has, eg:
(generate-> :first-arg (assoc :foo :bar))
I still get linting errors for arity and keywords not being the right type for the first argument to assoc
#2023-11-1414:02tragiclifestoriesso I feel like I'm Doing It Wrong:tm: but can't work out why#2023-11-1414:03tragiclifestoriesconfig.edn (extract):
{:hooks
 {:analyze-call {finops.spec/generate-> hooks.spec-generate/generate->}}}
#2023-11-1414:11imreThis might be easier with a macroexpand hook#2023-11-1414:14borkdudeThis looks wrong:
(api/token-node '->)
                   nil
#2023-11-1414:14borkdudeYou should probably write:
(api/token-node 'clojure.core/->)
(api/token-node nil)
#2023-11-1414:14borkdudeand (api/list-node ..) should be called with a list-like thing, not with a single node#2023-11-1414:15borkdudeif you call clj-kondo on the command line with --debug it will tell you that latter error#2023-11-1414:15borkdudeprobably also the other error for nil not being a node#2023-11-1414:24tragiclifestoriesYeah, all that fixed it. I think I understand the hooks API a little better now, thanks!#2023-11-1416:30Noah Bogartwould it be possible to return plain clojure data from a hook and have the analyzer convert it to the appropriate nodes as necessary?#2023-11-1416:41Noah Bogartas one who writes a lot of hooks lol, I wonder what's gained by having to manually write api/token-node and api/list-node etc. is there something special about those that a postwalk couldn't do?#2023-11-1416:42Noah Bogartor if you don't want to enable it for everyone, maybe there could be a helper function to do it that hook authors can use themselves#2023-11-1416:49borkdudeThis is what the :macroexpand hook does?#2023-11-1416:50Noah Bogartoh really?#2023-11-1416:50borkdudeyes#2023-11-1416:50Noah Bogartis that the only difference? for some reason, I thought :macroexpand did other stuff too#2023-11-1416:51borkdudethe differences are described in the docs, but in short, macroexpand is less powerful#2023-11-1416:51borkdudesince you don't have precise control over locations: numbers, etc cannot carry metadata#2023-11-1416:52borkdudebut for def-whatever like macros it's often enough#2023-11-1416:53Noah Bogartcan you call reg-finding! in them? does it work the same otherwise?
#2023-11-1416:54borkdudeyes, you can#2023-11-1416:54Noah Bogarthell yeah, okay#2023-11-1416:55Noah Bogartthe docs made it seem like it was more magical and couldn't do all the same stuff as :analyze-call#2023-11-1416:57borkdudemaybe you read magic into it?#2023-11-1416:57borkdudeit's not magic, but it's less accurate because of loss of data while translating to s-expressions and back#2023-11-1416:58borkdudealso there is currently a problem with namespaced keywords like ::foo/bar - those aren't properly converted back and forth#2023-11-1416:58borkdudenot many people have noticed that though#2023-11-1416:59Noah Bogartright. i think the lack of examples and the short docs made me think it was fundamentally different from :analyze-call. the analyze-call docs are long and have lots of examples, and the macroexpand docs don't say "this is analyze-call but with coercion".#2023-11-1416:59Noah Bogartmaybe i'll write up an example that calls api/reg-finding! to demonstrate that it all works the same as :analyze-call except for the returned type#2023-11-1417:01borkdudethat would be nice :)#2023-11-1417:01borkdudemacroexpand didn't exist at first when those docs got written#2023-11-1418:58Noah Bogarti did some looking through the hooks code and it turns out you have api/coerce in there already, so that's exactly what i was looking for lol. from
(let [defn-block (api/list-node (list* (api/token-node 'defn-)
                                           job-name
                                           (api/vector-node [fn-arg])
                                           body))
          node (api/list-node [(api/token-node 'do) defn-block job-name])]
      {:node node})))
to
(let [node (api/coerce `(do (defn- ~job-name [~fn-arg] ~@body)
                                ~job-name))]
      {:node node})))
#2023-11-1419:16Noah Bogartonce again, you've outdone yourself and have made my development life easier. thank you!#2023-11-1421:14borkdudethanks!#2023-11-1417:04mkvlrcould clj-kondo implement a cyclic dep linter? This is one of the things where I currently restart my process which is annoying and slow. Maybe I should also into a better way to repl debug this.#2023-11-1418:30borkdudeI think clojure-lsp is in a better place to do this than clj-kondo since clojure-lsp runs as a server and scans your entire project. It is possible to use the existing data as shown here: https://github.com/clj-kondo/clj-kondo/blob/12342316a4eecf1c543f1f1dbfd283b6cc68dc68/analysis/README.md?plain=1#L454#2023-11-1421:18borkdudehttps://blog.tvaisanen.com/take-your-linting-game-to-the-next-level?showSharer=true#2023-11-1422:18DerekWas there a change in behavior between 2023.09.07 and 2023.10.20 related to incorrect lint-as rules?#2023-11-1422:20DerekA macro that should have been linted as clojure.core/fn was linted as clj-kondo.lint-as/def-catch-all incorrectly#2023-11-1422:20DerekWith 2023.09.07 it runs, but in 2023.10.20 it fails to parse and throws an NPE#2023-11-1422:20DerekI'm carving out a small repro#2023-11-1422:30borkdudeThis bug was already reported and fixed on master.#2023-11-1422:31DerekOk great#2023-11-1422:31DerekThank you#2023-11-1422:31borkdudehttps://github.com/clj-kondo/clj-kondo/commit/e49369b0886b104832eb9f67711042987dc166df#2023-11-1422:33DerekWe're fixing our lint-as config